OpenLayers OpenLayers

Ticket #1498 (closed feature: fixed)

Opened 8 months ago

Last modified 8 months ago

Easily turning off/overriding default select and temporary intent styles

Reported by: sbenthall Assigned to: ahocevar
Priority: minor Milestone: 2.6 Release
Component: Style Version: 2.6 RC1
Keywords: pullup Cc:
State: Complete

Description

Currently, when I try to build a simple StyleMap that uses only one Style, I can pass that style in to the StyleMap's initializer and it will become that StyleMaps "default" intent style.

However, when I (e.g.) select a feature, the symbolizer applies an additional style, the default style specified in OpenLayers.Feature.Vector.styleselect?

Apparently in order to override this select style, I need to explicitly override it by passing the StyleMap a bloaty object containing a few identical styles, one for each intent.

That's not as awesome as it could be.

Attachments

1498-r6810-A0.patch (1.9 kB) - added by ahocevar on 04/07/08 15:41:59.
1498-r6810-B0.patch (2.6 kB) - added by ahocevar on 04/07/08 17:13:33.
more verbose ND comments, tests pass.

Change History

04/07/08 12:37:47 changed by ahocevar

Seb: what would we have to do to make it as awesome as it could be in your opinion?

Remember that you only need to include the properties that you want to be different from the default style in your select style. So if you want to have your default features filled red, and the selected ones filled yellow, you could define your styleMap like this:

var styleMap = new OpenLayers.StyleMap({
    "default": {
        strokeWidth: 1,
        strokeColor: "black",
        fillColor: "red"},
    "select": {
        fillColor: "yellow"}
});

That does not feel too bloaty for me. How 'bout you?

04/07/08 12:40:47 changed by crschmidt

The fact that with no "select" style, the default is not to use the same style as the 'default' style, but instead to fall back to some other style, is what bothers me: See http://thematicmapping.org/experiments/openlayers/propsymbols.html , where the feature size shrinks from the set pointRadius to a pointRadius of 6, then the feature is no longer selected, so it resizes again, etc. etc. and you get a pretty nasty loop.

04/07/08 12:47:22 changed by sbenthall

Yeah, crschmidt's example is exactly the problem we've been getting in our application; unwanted resizing of our markers.


In your example, you pass in an object which is a hash of symbolizers. But if I want to have the same Style--complete with rules--for both the 'default' and 'select' intents, I can't just pass in those symbolizers, right?

What I would like to see as a user of the OL library is an easy way for me to construct a StyleMap that gives me control over it, without knowing the particular symbolizer used as the default 'select' intent style defined in an OL library class somewhere that I have to dig for. If I could just pass in a single Style to the StyleMap initializer and have it take over entirely, that would be ideal. If I had to throw in a boolean 'override' argument, that would be cool too.

04/07/08 12:49:24 changed by crschmidt

sbenthall: Do you want no visible difference when a feature is selected? That's a somewhat unusual requirement, I think. In general, you would expect that some visual indication is there when a feature is selected, right? Are you wanting to abandon that (and thus get the equivilant of {'default': style, 'select': style} )?

04/07/08 12:59:13 changed by ahocevar

Seb, you can perfectly mix a default style (OpenLayers.Style with rules) and a select style (hash with only the properties you want to be different for selected features):

var style = new OpenLayers.Style(...);
var styleMap = new OpenLayers.StyleMap({
    "default": style,
    "select": {fillColor: "yellow"}
});
Am I right that this is exactly what you want?

04/07/08 14:30:58 changed by sbenthall

crschmidt: Yes, that's exactly what we want for our application, for now. (When we select a feature, we get a popup, which is indication enough. We'd rather our externalGraphic markers keep looking the same)

From our point of view, passing a StyleMap a single Style as an argument and then having the way features look on the map change in ways that we never specified in that Style feels really weird. The OL defaults (sizing, in this case) seem totally bizarre and feel like they come out of nowhere.

{'default': style, 'select': style, 'temporary': style} is fine, I guess, if what I'm talking about is unorthodox from a geo- perspective, but in my opinion it's a counterintuitive way of going about it when there is the option of passing the StyleMap a single Style in the constructor.

ahocevar: That's good to know. Thanks. But that strategy still requires that as a user of the StyleMap I need to go into the Feature.Vector.style defaults and figure out, piecewise, which styles I need to override, right? It would make more sense to me (again, just as a naive user of the library) if I didn't have to dig so much to get my Style, which has everything I want about feature displays in it, to apply without exception to my map.

crschmidt's object with many hashes going to the same Style is pretty clean, but as a user I'm still left with this feeling of "Why the hell..."

04/07/08 14:34:00 changed by crschmidt

I think that the fact that you're overriding the style (to set an externalGraphic) is more likely to indicate that you 'know what you're doing' than anything else, and if you know what you're doing, you need to do a bit more work.

Compare to http://crschmidt.net/mapping/choropleth.html , where I've got a stylemap where I'm just passing the StyleMap: when I hover, the countries turn blue. If we took your desired behavior, that would no longer be the case: They would keep their current style rules.

I can see both sides of an argument here, and I don't know which one is right.

04/07/08 15:09:25 changed by sbenthall

Ok, that sort of makes sense. I won't push the issue any more. In general though, in working with OL we've encountered a lot of cases where we felt like it takes a lot of work to fight the default behavior. If anybody else agrees that there is an issue in this particular case, I'd suggest as a minimal solution a boolean option which defaults to false and gives behavior consistent with your choropleth example.

04/07/08 15:41:59 changed by ahocevar

  • attachment 1498-r6810-A0.patch added.

04/07/08 15:43:09 changed by ahocevar

1498-r6810-A0.patch changes the StyleMap constructor. If only one style hash or style object is passed, this will be used for all known render intents. No more digging into OpenLayers.Feature.Vector.style.*

04/07/08 15:44:34 changed by sbenthall

thanks, ahocevar. I appreciate it!

04/07/08 16:01:26 changed by ahocevar

  • state set to Review.

04/07/08 16:01:34 changed by ahocevar

  • milestone changed from 2.7 Release to 2.6 Release.

04/07/08 16:34:11 changed by ahocevar

1498-r6810-B0.patch is an alternative. It defines only fillColor and strokeColor for the select and temporary intents, which means that all other symbolizer properties will be taken from the default intent.

04/07/08 16:58:23 changed by ahocevar

  • state changed from Review to Needs More Work.

have to check why tests fail.

04/07/08 17:07:18 changed by ahocevar

  • milestone changed from 2.6 Release to 2.7 Release.

Whatever, after all I don't care if this goes into 2.6 or not.

04/07/08 17:13:33 changed by ahocevar

  • attachment 1498-r6810-B0.patch added.

more verbose ND comments, tests pass.

04/07/08 17:57:27 changed by ahocevar

  • state changed from Needs More Work to Review.

Tests pass in FF2 and IE6.

04/07/08 18:31:29 changed by tschaub

Here's an imaginary FAQ:

Q: What's the default behavior with regard to render intent (as if people really ask questions like that)?
A: The default behavior is that the select render intent results in a different style than the default render intent - like people expect (you know, ArcMap people) 'cause we're smart like that.

Q: Great, how do I get this default behavior?
A: Oh, it's not hard really, you do nothing at all (construct a layer with no StyleMap).

Q: Ok, my boss came back and said he wanted distinct styles for "default" and "select" rendering intents - but (sigh) he wants them to be different than the OpenLayers defaults.
A: No problem, construct a style map with multiple styles - one for each intent:

    // untested code, run at your own risk
    var layer = new OpenLayers.Vector("My Layer", {
        styleMap: new OpenLayers.StyleMap({
            "default": defStyle,
            "select": selStyle
        })
    });

Q: Ok, that worked great. Now I decided I don't want multiple styles any more - just one. How about that?
A: No biggie, just construct your style map with a single style - easy pie:

    new OpenLayers.StyleMap({strokeColor: "maroon"})

Anyway, if someone thinks there are more frequently asked questions or simpler answers, please reply. (I'd vote for the first patch in 2.6.)

04/08/08 00:21:14 changed by tschaub

  • state changed from Review to Commit.

I think this is good to go. Whether or not it gets in to 2.6 is up to the release manager :)

I'd like to see the first patch in - but I don't want to be the only one who thinks that way. Please comment here on how the second patch makes more sense.

04/08/08 07:18:54 changed by crschmidt

The second patch would make more sense to me if you could add a rule-based Style() to a layer without using a stylemap. This would allow you to say: Layer("blah", {style: new OpenLayers.STyle(rules, blah blah blah}); -- like http://crschmidt.net/mapping/choropleth.html tries to (but instead gets no style at all).

You can't do that. So if you *only* care about overriding the 'default' style with a Rule based symbolizer... you have to do OpenLayers.StyleMap({'default': style}) instead of just creating StyleMap(style).

(I'm sure you'll tell me this is due to backwards compatibility, and I have only myself to blame. I accept this as a given, but that doesn't mean that I enjoy the specific result of that behavior.)

And we all know that the bikeshed should be painted red.

In reality, all of these solutions work fine so long as they're sufficiently documented. WE've now written three teatises on why it should be one way or the other between here and IRC, and that time is all much better spent on docs, because no matter what we do, people will be confused.

Andreas, please commit to trunk. I'll make time over lunch to pull this (and the stuff that Tim did overnight) into OL 2.6RC2.

04/08/08 09:27:01 changed by crschmidt

  • milestone changed from 2.7 Release to 2.6 Release.

04/09/08 05:12:09 changed by ahocevar

  • keywords set to pullup.
  • state changed from Commit to Pullup.

(In [6827]) Changed StyleMap constructor so that all render intents will be set if only one Style object or symbolizer hash is passed. This is the first patch attached to #1498, which got slightly more votes thaan the second one. r=crschmidt,tschaub (pullup #1498)

04/09/08 13:59:52 changed by crschmidt

  • status changed from new to closed.
  • state changed from Pullup to Complete.
  • resolution set to fixed.

(In r6835) Finish pullups for RC2.

#1498 Easily turning off/overriding default select and temporary intent styles #1501 GeoRSS format tests fail in Safari #1502 Events register method fails if listeners member is not an array #1503 panning off for odd-sized viewport #1504 doc review