PageRenderTime 73ms CodeModel.GetById 21ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 0ms

/webportal/src/main/java/au/org/emii/portal/composer/LayerLegendComposer2.java

http://alageospatialportal.googlecode.com/
Java | 875 lines | 704 code | 128 blank | 43 comment | 160 complexity | 19d9ab6a13cc624f86c2c5405f22e884 MD5 | raw file
  1/*
  2 * To change this template, choose Tools | Templates
  3 * and open the template in the editor.
  4 */
  5package au.org.emii.portal.composer;
  6
  7import au.org.emii.portal.menu.MapLayer;
  8import au.org.emii.portal.settings.SettingsSupplementary;
  9import au.org.emii.portal.util.GeoJSONUtilities;
 10import au.org.emii.portal.util.LayerUtilities;
 11import java.awt.Color;
 12import java.net.URLEncoder;
 13import java.util.ArrayList;
 14import java.util.Collections;
 15import java.util.HashMap;
 16import java.util.List;
 17import java.util.Map;
 18import org.ala.spatial.data.BiocacheQuery;
 19import org.ala.spatial.data.LegendObject;
 20import org.ala.spatial.data.Query;
 21import org.ala.spatial.data.QueryField;
 22import org.ala.spatial.data.UploadQuery;
 23import org.ala.spatial.util.CommonData;
 24import org.ala.spatial.util.LegendMaker;
 25import org.apache.commons.httpclient.HttpClient;
 26import org.apache.commons.httpclient.methods.GetMethod;
 27import org.apache.commons.lang.StringEscapeUtils;
 28import org.apache.commons.lang.StringUtils;
 29import org.zkoss.zk.ui.Executions;
 30import org.zkoss.zk.ui.event.Event;
 31import org.zkoss.zk.ui.event.EventListener;
 32import org.zkoss.zul.Button;
 33import org.zkoss.zul.Checkbox;
 34import org.zkoss.zul.Combobox;
 35import org.zkoss.zul.Comboitem;
 36import org.zkoss.zul.Div;
 37import org.zkoss.zul.Doublebox;
 38import org.zkoss.zul.Hbox;
 39import org.zkoss.zul.Image;
 40import org.zkoss.zul.Intbox;
 41import org.zkoss.zul.Label;
 42import org.zkoss.zul.Listbox;
 43import org.zkoss.zul.Radio;
 44import org.zkoss.zul.Radiogroup;
 45import org.zkoss.zul.Slider;
 46import org.zkoss.zul.Textbox;
 47
 48/**
 49 *
 50 * @author Adam
 51 */
 52public class LayerLegendComposer2 extends GenericAutowireAutoforwardComposer {
 53
 54    SettingsSupplementary settingsSupplementary = null;
 55    Slider opacitySlider;
 56    Label opacityLabel;
 57    Slider redSlider;
 58    Slider greenSlider;
 59    Slider blueSlider;
 60    Slider sizeSlider;
 61    Checkbox chkUncertaintySize;
 62    public Button btnPointsCluster;
 63    Label lblFupload;
 64    Label redLabel;
 65    Label greenLabel;
 66    Label blueLabel;
 67    Label sizeLabel;
 68    Listbox activeLayersList;
 69    Div layerControls;
 70    Div clusterpoints;
 71    Div uncertainty;
 72    Hbox uncertaintyLegend;
 73    Div colourChooser;
 74    Div sizeChooser;
 75    Image legendImg;
 76    Image legendImgUri;
 77    Div legendHtml;
 78    Label legendLabel;
 79    Div divUserColours;
 80    Hbox dAnimationStep;
 81    Combobox cbColour;
 82    Comboitem ciColourUser; //User selected colour
 83    Label layerName;
 84    EventListener listener;
 85    Query query;
 86    public Radiogroup pointtype;
 87    public Radio rPoint, rCluster, rGrid;
 88    MapLayer mapLayer;
 89    boolean inInit = false;
 90    Textbox txtLayerName;
 91    String sLayerName;
 92    Button btnLayerName;
 93    Label lInGroupCount;
 94    Button btnCreateGroupLayers;
 95    Div dGroupBox;
 96    Combobox cbClassificationGroup;
 97    Div divClassificationPicker;
 98    Div divAnimation;
 99    Combobox cbAnimationDenomination;
100    Button btnAnimationStart;
101    Button btnAnimationStop;
102    Intbox intAnimationStep;
103    Intbox intAnimationYearStart;
104    Intbox intAnimationYearEnd;
105    //Label lblAnimationLabel;
106    Doublebox dblAnimationSeconds;
107
108    @Override
109    public void afterCompose() {
110        super.afterCompose();
111        cbColour.setSelectedIndex(0);
112    }
113
114    public void onScroll$opacitySlider(Event e) {
115        float opacity = ((float) opacitySlider.getCurpos()) / 100;
116        int percentage = (int) (opacity * 100);
117        opacitySlider.setCurpos(percentage);
118        opacityLabel.setValue(percentage + "%");
119        refreshLayer();
120    }
121
122    public void updateLegendImage() {
123        LegendMaker lm = new LegendMaker();
124        int red = redSlider.getCurpos();
125        int blue = blueSlider.getCurpos();
126        int green = greenSlider.getCurpos();
127        Color c = new Color(red, green, blue);
128
129        legendImg.setContent(lm.singleCircleImage(c, 60, 60, 50.0));
130//        sizeChooser.setVisible(true);
131
132        if (cbColour.getSelectedItem() != ciColourUser) {
133            legendHtml.setVisible(true);
134            legendImg.setVisible(false);
135
136            showPointsColourModeLegend();
137        } else {
138            legendImg.setVisible(true);
139            legendHtml.setVisible(false);
140        }
141    }
142
143    public void onScroll$sizeSlider() {
144        int size = sizeSlider.getCurpos();
145        sizeLabel.setValue(String.valueOf(size));
146        refreshLayer();
147    }
148
149    public void onScroll$blueSlider() {
150        int blue = blueSlider.getCurpos();
151        blueLabel.setValue(String.valueOf(blue));
152        updateLegendImage();
153        refreshLayer();
154    }
155
156    public void onScroll$redSlider() {
157        int red = redSlider.getCurpos();
158        redLabel.setValue(String.valueOf(red));
159        updateLegendImage();
160        refreshLayer();
161    }
162
163    public void onScroll$greenSlider() {
164        int green = greenSlider.getCurpos();
165        greenLabel.setValue(String.valueOf(green));
166        updateLegendImage();
167        refreshLayer();
168    }
169
170    public void selectColour(Object obj) {
171        Div div = (Div) obj;
172        String style = div.getStyle();
173        String background_color = "background-color";
174        int a = style.indexOf(background_color);
175        if (a >= 0) {
176            String colour = style.substring(a + background_color.length() + 2, a + background_color.length() + 8);
177            int r = Integer.parseInt(colour.substring(0, 2), 16);
178            int g = Integer.parseInt(colour.substring(2, 4), 16);
179            int b = Integer.parseInt(colour.substring(4, 6), 16);
180
181            redSlider.setCurpos(r);
182            greenSlider.setCurpos(g);
183            blueSlider.setCurpos(b);
184            redLabel.setValue(String.valueOf(r));
185            greenLabel.setValue(String.valueOf(g));
186            blueLabel.setValue(String.valueOf(b));
187
188            updateLegendImage();
189
190            refreshLayer();
191        }
192    }
193
194    public void onChange$cbColour(Event event) {
195        mapLayer.setHighlight(null);
196        updateUserColourDiv();
197        updateLegendImage();
198        refreshLayer();
199    }
200
201    void updateUserColourDiv() {
202        if (cbColour.getSelectedItem() == ciColourUser) {
203            divUserColours.setVisible(true);
204        } else {
205            divUserColours.setVisible(false);
206        }
207    }
208
209    void updateComboBoxesColour(MapLayer currentSelection) {
210        if (currentSelection.isClustered()) {
211            cbColour.setSelectedItem(ciColourUser);
212            cbColour.setDisabled(true);
213        } else {
214            cbColour.setDisabled(false);
215            for (int i = 0; i < cbColour.getItemCount(); i++) {
216                if (cbColour.getItemAtIndex(i).getValue() != null
217                        && cbColour.getItemAtIndex(i).getValue().equals(currentSelection.getColourMode())) {
218                    cbColour.setSelectedIndex(i);
219                }
220            }
221            updateUserColourDiv();
222        }
223    }
224
225    void showPointsColourModeLegend() {
226        //remove all
227        while (legendHtml.getChildren().size() > 0) {
228            legendHtml.removeChild(legendHtml.getFirstChild());
229        }
230
231        //TODO: make work for query instead of lsid
232        //1. register legend
233        //String pid = registerPointsColourModeLegend(lsid, (String) cbColour.getSelectedItem().getValue());
234
235        //put any parameters into map
236        Map map = new HashMap();
237        //map.put("pid", pid);
238        map.put("query", query);
239        map.put("layer", mapLayer);
240        map.put("readonly", "true");
241
242        String colourmode = (String) cbColour.getSelectedItem().getValue();
243        if (!mapLayer.getColourMode().equals("grid")
244                && query.getLegend(colourmode).getCategories() != null) {
245            map.put("checkmarks", "true");
246        }
247
248        try {
249            LegendObject lo = query.getLegend(colourmode);
250            if (lo != null) {
251                mapLayer.setData("legendobject", lo);
252            }
253        } catch (Exception e) {
254            e.printStackTrace();
255        }
256
257        map.put("colourmode", colourmode);
258
259        try {
260            Executions.createComponents(
261                    "/WEB-INF/zul/AnalysisClassificationLegend.zul", legendHtml, map);
262        } catch (Exception e) {
263            e.printStackTrace();
264        }
265    }
266
267    public void init(MapLayer ml, Query query, int red, int green, int blue, int size, int opacity, String colourMode, int type, boolean uncertainty, EventListener listener) {
268        mapLayer = ml;
269        inInit = true;
270
271        txtLayerName.setValue(ml.getDisplayName());
272        sLayerName = ml.getDisplayName();
273
274        this.query = query;
275
276        opacitySlider.setCurpos(opacity);
277        onScroll$opacitySlider(null);
278
279        redSlider.setCurpos(red);
280        onScroll$redSlider();
281
282        greenSlider.setCurpos(green);
283        onScroll$greenSlider();
284
285        blueSlider.setCurpos(blue);
286        onScroll$blueSlider();
287
288        sizeSlider.setCurpos(size);
289        onScroll$sizeSlider();
290        
291        for (Comboitem item : (List<Comboitem>) cbColour.getItems()) {
292            if (item.getValue() != null && item.getValue().equals(colourMode)) {
293                cbColour.setSelectedItem(item);
294                //System.out.println("LAYER LEGEND COMPOSER 2: set colour by item: " + item);
295                break;
296            }
297        }
298        
299        
300        this.listener = listener;
301
302        if (type == 0) {
303            pointtype.setSelectedItem(rGrid);
304        } else if (type == 1) {
305            pointtype.setSelectedItem(rCluster);
306        } else if (type == 2) {
307            pointtype.setSelectedItem(rPoint);
308        }
309
310        chkUncertaintySize.setChecked(uncertainty);
311
312        updateUserColourDiv();
313        updateLegendImage();
314
315        setupLayerControls(ml);
316        
317        
318        updateAnimationDiv();
319
320        String script = "mapFrame.stopAllAnimations();";
321        getMapComposer().getOpenLayersJavascript().execute(script);
322
323        inInit = false;
324    }
325
326    public int getRed() {
327        return redSlider.getCurpos();
328    }
329
330    public int getGreen() {
331        return greenSlider.getCurpos();
332    }
333
334    public int getBlue() {
335        return blueSlider.getCurpos();
336    }
337
338    public int getSize() {
339        return sizeSlider.getCurpos();
340    }
341
342    public int getOpacity() {
343        return opacitySlider.getCurpos();
344    }
345
346    public String getColourMode() {
347        if (pointtype.getSelectedItem() == rGrid) {
348            return "grid";
349        } else {
350            return (String) cbColour.getSelectedItem().getValue();
351        }
352    }
353
354    public void onClick$btnApply(Event event) {
355        if (listener != null) {
356            try {
357                listener.onEvent(null);
358            } catch (Exception e) {
359                e.printStackTrace();
360            }
361        }
362    }
363
364    public void onClick$btnClose(Event event) {
365        this.detach();
366    }
367
368    private void showPointsColourModeLegend(MapLayer m) {
369        //remove all
370        while (legendHtml.getChildren().size() > 0) {
371            legendHtml.removeChild(legendHtml.getFirstChild());
372        }
373
374        //1. register legend
375        String colourMode = (String) cbColour.getSelectedItem().getValue();
376        if (pointtype.getSelectedItem() == rGrid) {
377            colourMode = "grid";
378        }
379
380        //put any parameters into map
381        Map map = new HashMap();
382        map.put("query", m.getData("query"));
383        map.put("layer", m);
384        map.put("readonly", "true");
385        map.put("colourmode", colourMode);
386
387        String colourmode = (String) cbColour.getSelectedItem().getValue();
388        if (!m.getColourMode().equals("grid")
389                && query.getLegend(colourmode).getCategories() != null) {
390            map.put("checkmarks", "true");
391        }
392        try {
393            LegendObject lo = ((Query) m.getData("query")).getLegend(colourmode);
394            if (lo != null) {
395                m.setData("legendobject", lo);
396            }
397        } catch (Exception e) {
398            e.printStackTrace();
399        }
400
401        try {
402            Executions.createComponents(
403                    "/WEB-INF/zul/AnalysisClassificationLegend.zul", legendHtml, map);
404        } catch (Exception e) {
405            e.printStackTrace();
406        }
407    }
408
409    public int getPointType() {
410        if (pointtype.getSelectedItem() == rGrid) {
411            return 0;
412        } else if (pointtype.getSelectedItem() == rCluster) {
413            return 1;
414        } else {//if(pointtype.getSelectedItem() == rPoint) {
415            return 2;
416        }
417    }
418
419    public boolean getUncertainty() {
420        return chkUncertaintySize.isChecked();
421    }
422
423    public void onCheck$chkUncertaintySize() {
424        refreshLayer();
425        uncertaintyLegend.setVisible(chkUncertaintySize.isChecked());
426    }
427
428    public void onCheck$pointtype(Event event) {
429        Radio selectedItem = pointtype.getSelectedItem();
430        try {
431            selectedItem = (Radio) ((org.zkoss.zk.ui.event.ForwardEvent) event).getOrigin().getTarget();
432            pointtype.setSelectedItem(selectedItem);
433            mapLayer.setHighlight(null);
434        } catch (Exception e) {
435        }
436
437        refreshLayer();
438
439        setupLayerControls(mapLayer);
440    }
441
442    void refreshLayer() {
443        sLayerName = txtLayerName.getValue();
444        if (listener != null && !inInit) {
445            try {
446                listener.onEvent(null);
447            } catch (Exception e) {
448                e.printStackTrace();
449            }
450        }
451    }
452
453    public void setupLayerControls(MapLayer m) {
454
455        MapLayer currentSelection = m;
456
457        if (currentSelection != null) {
458            if (currentSelection.isDynamicStyle()) {
459                if (m.getColourMode().equals("grid")) {
460                    pointtype.setSelectedItem(rGrid);
461                } else {
462                    pointtype.setSelectedItem(rPoint);
463                }
464
465                //fill cbColour
466                setupCBColour(m);
467
468                updateComboBoxesColour(currentSelection);
469
470                updateAdhocGroupContols(m);
471
472
473                if (currentSelection.getColourMode().equals("-1")) {
474                    divUserColours.setVisible(true);
475                } else {
476                    divUserColours.setVisible(false);
477                }
478
479                if (currentSelection.getGeometryType() != GeoJSONUtilities.POINT) {
480                    sizeChooser.setVisible(false);
481                    uncertainty.setVisible(false);
482                } else {
483                    sizeChooser.setVisible(pointtype.getSelectedItem() != rGrid);
484                    if (m.getGeoJSON() != null && m.getGeoJSON().length() > 0) {
485                        uncertainty.setVisible(false);
486                    } else {
487                        uncertainty.setVisible(!(query instanceof UploadQuery));
488                    }
489                }
490
491                colourChooser.setVisible(pointtype.getSelectedItem() != rGrid);
492                uncertainty.setVisible(pointtype.getSelectedItem() != rGrid);
493
494                if ((cbColour.getSelectedItem() != ciColourUser || pointtype.getSelectedItem() == rGrid)
495                        && m.isSpeciesLayer() /*&& !m.isClustered()*/) {
496                    legendHtml.setVisible(true);
497                    legendImg.setVisible(false);
498
499                    showPointsColourModeLegend(m);
500                } else {
501                    legendImg.setVisible(true);
502                    legendHtml.setVisible(false);
503                }
504
505            } else if (currentSelection.getSelectedStyle() != null) {
506                /* 1. classification legend has uri with ".zul" content
507                 * 2. prediction legend works here
508                 * TODO: do this nicely when implementing editable prediction layers
509                 */
510                String legendUri = currentSelection.getSelectedStyle().getLegendUri();
511                if (legendUri != null && legendUri.indexOf(".zul") >= 0) {
512                    //remove all
513                    while (legendHtml.getChildren().size() > 0) {
514                        legendHtml.removeChild(legendHtml.getFirstChild());
515                    }
516
517                    //put any parameters into map
518                    Map map = null;
519                    if (legendUri.indexOf("?") > 0) {
520                        String[] parameters = legendUri.substring(legendUri.indexOf("?") + 1,
521                                legendUri.length()).split("&");
522                        if (parameters.length > 0) {
523                            map = new HashMap();
524                        }
525                        for (String p : parameters) {
526                            String[] parameter = p.split("=");
527                            if (parameter.length == 2) {
528                                map.put(parameter[0], parameter[1]);
529                            }
530                        }
531                        legendUri = legendUri.substring(0, legendUri.indexOf("?"));
532                    }
533
534                    //open .zul with parameters
535                    Executions.createComponents(
536                            legendUri, legendHtml, map);
537
538                    legendHtml.setVisible(true);
539                    legendImgUri.setVisible(false);
540                    legendLabel.setVisible(true);
541                } else {
542                    legendImgUri.setSrc(legendUri);
543                    legendImgUri.setVisible(true);
544                    legendHtml.setVisible(false);
545                    legendLabel.setVisible(false);
546                }
547                legendImg.setVisible(false);
548                colourChooser.setVisible(false);
549                sizeChooser.setVisible(false);
550            } else if (currentSelection.getCurrentLegendUri() != null) {
551                // works for normal wms layers
552                legendImgUri.setSrc(currentSelection.getCurrentLegendUri());
553                legendImgUri.setVisible(true);
554                legendHtml.setVisible(false);
555                legendLabel.setVisible(false);
556                legendImg.setVisible(false);
557                colourChooser.setVisible(false);
558                sizeChooser.setVisible(false);
559            } else {
560                //image layer?
561                legendImgUri.setVisible(false);
562                legendHtml.setVisible(false);
563                legendLabel.setVisible(false);
564                legendImg.setVisible(false);
565                colourChooser.setVisible(false);
566                sizeChooser.setVisible(false);
567            }
568            layerControls.setVisible(true);
569            layerControls.setAttribute("activeLayerName", currentSelection.getName());
570            setupForClassificationLayers();
571        }
572
573        if (m != null && m.isSpeciesLayer()) {
574            clusterpoints.setVisible(true);
575            cbColour.setDisabled(m.isClustered());
576        } else {
577            clusterpoints.setVisible(false);
578            cbColour.setDisabled(true);
579        }
580
581        uncertaintyLegend.setVisible(chkUncertaintySize.isChecked());
582    }
583
584    public String getDisplayName() {
585        return txtLayerName.getValue();
586    }
587
588//    public void onChanging$txtLayerName(Event event) {
589//        refreshLayer();
590//    }
591//    public void onChange$txtLayerName(Event event) {
592//        refreshLayer();
593//    }
594    public void onOK$txtLayerName(Event event) {
595        refreshLayer();
596        btnLayerName.setDisabled(true);
597    }
598
599    public void onBlur$txtLayerName(Event event) {
600        if (sLayerName.equals(txtLayerName.getValue())) {
601            btnLayerName.setDisabled(true);
602        }
603    }
604
605    private void setupCBColour(MapLayer m) {
606        for (int i = 0; i < cbColour.getItemCount(); i++) {
607            if (cbColour.getItemAtIndex(i) != ciColourUser) {
608                cbColour.removeItemAt(i);
609                i--;
610            }
611        }
612
613        Query q = (Query) m.getData("query");
614        if (q != null) {
615            ArrayList<QueryField> fields = q.getFacetFieldList();
616            Collections.sort(fields, new QueryField.QueryFieldComparator());
617            Comboitem seperator = new Comboitem("seperator");
618            String lastGroup = null;
619      
620
621            for(QueryField field : fields){
622                String newGroup = field.getGroup().getName();
623                if(!newGroup.equals(lastGroup)){
624                    Comboitem sep = new Comboitem("seperator");
625                    sep.setLabel("---------------" + StringUtils.center(newGroup, 19) + "---------------");
626                    sep.setParent(cbColour);
627                    sep.setDisabled(true);
628                    lastGroup = newGroup;
629                }
630                Comboitem ci = new Comboitem(field.getDisplayName());
631                ci.setValue(field.getName());
632                ci.setParent(cbColour);
633            }
634            
635
636        }
637    }
638
639    public void onClick$btnCreateGroupLayers(Event event) {
640        Query query;
641        if (mapLayer != null
642                && (query = (Query) mapLayer.getData("query")) != null
643                && query.flagRecordCount() != 0) {
644
645            Query inGroup = query.newFlaggedRecords(true);
646            Query outGroup = query.newFlaggedRecords(false);
647
648            getMapComposer().mapSpecies(inGroup, mapLayer.getDisplayName() + " in group", "species", -1, LayerUtilities.SPECIES, null, -1, MapComposer.DEFAULT_POINT_SIZE, MapComposer.DEFAULT_POINT_OPACITY, MapComposer.nextColour());
649            getMapComposer().mapSpecies(outGroup, mapLayer.getDisplayName() + " out group", "species", -1, LayerUtilities.SPECIES, null, -1, MapComposer.DEFAULT_POINT_SIZE, MapComposer.DEFAULT_POINT_OPACITY, MapComposer.nextColour());
650        }
651    }
652
653    private void updateAdhocGroupContols(MapLayer m) {
654        if (m == null) {
655            dGroupBox.setVisible(false);
656            return;
657        }
658        Query query = (Query) m.getData("query");
659        if (query == null || query.flagRecordCount() == 0) {
660            dGroupBox.setVisible(false);
661        } else {
662            dGroupBox.setVisible(true);
663
664            lInGroupCount.setValue(query.flagRecordCount() + (query.flagRecordCount() == 1 ? " record" : " records"));
665        }
666    }
667
668    private void setupForClassificationLayers() {
669        if (mapLayer != null && mapLayer.getSubType() == LayerUtilities.ALOC) {
670            divClassificationPicker.setVisible(true);
671
672            //reset content
673            Integer groupCount = (Integer) mapLayer.getData("classificationGroupCount");
674            if (groupCount == null) {
675                mapLayer.setData("classificationGroupCount", getClassificationGroupCount(mapLayer.getName().replace("aloc_", "")));
676                groupCount = 0;
677            }
678            for (int i = cbClassificationGroup.getItemCount() - 1; i >= 0; i--) {
679                cbClassificationGroup.removeItemAt(i);
680            }
681            Comboitem ci = new Comboitem("none");
682            ci.setParent(cbClassificationGroup);
683
684            for (int i = 1; i <= groupCount; i++) {
685                new Comboitem("Group " + i).setParent(cbClassificationGroup);
686            }
687
688            //is there a current selection?
689            Integer groupSelection = (Integer) mapLayer.getData("classificationSelection");
690            if (groupSelection == null) {
691                groupSelection = 0;
692                mapLayer.setData("classificationSelection", groupSelection);
693            }
694            cbClassificationGroup.setSelectedIndex(groupSelection);
695
696        } else {
697            divClassificationPicker.setVisible(false);
698        }
699    }
700
701    //sld substitution strings
702    private static final String SUB_LAYERNAME = "*layername*";
703    private static final String SUB_COLOUR = "0xff0000"; //"*colour*";
704    private static final String SUB_MIN_MINUS_ONE = "*min_minus_one*";
705    private static final String SUB_MIN = "*min*";
706    private static final String SUB_MAX_PLUS_ONE = "*max_plus_one*";
707    String polygonSld =
708            "<?xml version=\"1.0\" encoding=\"UTF-8\"?><StyledLayerDescriptor xmlns=\"http://www.opengis.net/sld\">"
709            + "<NamedLayer><Name>ALA:" + SUB_LAYERNAME + "</Name>"
710            + "<UserStyle><FeatureTypeStyle><Rule><RasterSymbolizer><Geometry></Geometry>"
711            + "<ColorMap>"
712            + "<ColorMapEntry color=\"" + SUB_COLOUR + "\" opacity=\"0\" quantity=\"" + SUB_MIN_MINUS_ONE + "\"/>"
713            + "<ColorMapEntry color=\"" + SUB_COLOUR + "\" opacity=\"1\" quantity=\"" + SUB_MIN + "\"/>"
714            + "<ColorMapEntry color=\"" + SUB_COLOUR + "\" opacity=\"0\" quantity=\"" + SUB_MAX_PLUS_ONE + "\"/>"
715            + "</ColorMap></RasterSymbolizer></Rule></FeatureTypeStyle></UserStyle></NamedLayer></StyledLayerDescriptor>";
716
717    public void onChange$cbClassificationGroup(Event event) {
718        if (mapLayer != null) {
719            mapLayer.setData("classificationSelection", new Integer(cbClassificationGroup.getSelectedIndex()));
720
721            String baseUri = mapLayer.getUri();
722            int pos = baseUri.indexOf("&sld_body=");
723            if (pos > 0) {
724                baseUri = baseUri.substring(0, pos);
725            }
726            String layername = mapLayer.getName();
727            int n = cbClassificationGroup.getSelectedIndex();
728            if (n > 0) {
729                try {
730                    String sldBodyParam = "&sld_body=" + formatSld(URLEncoder.encode(polygonSld, "UTF-8"), layername, String.valueOf(n - 1), String.valueOf(n), String.valueOf(n), String.valueOf(n + 1));
731                    mapLayer.setUri(baseUri + sldBodyParam);
732                } catch (Exception e) {
733                    e.printStackTrace();
734                }
735            } else {
736                mapLayer.setUri(baseUri);
737            }
738            getMapComposer().reloadMapLayerNowAndIndexes(mapLayer);
739        }
740    }
741
742    private String formatSld(String sld, String layername, String min_minus_one, String min, String max, String max_plus_one) {
743        return sld.replace(SUB_LAYERNAME, layername).replace(SUB_MIN_MINUS_ONE, min_minus_one).replace(SUB_MIN, min).replace(SUB_MAX_PLUS_ONE, max_plus_one);
744    }
745
746    public Integer getClassificationGroupCount(String pid) {
747        Integer i = 0;
748        try {
749            StringBuffer sbProcessUrl = new StringBuffer();
750            sbProcessUrl.append(CommonData.satServer + "/output/aloc/" + pid + "/classification_means.csv");
751
752            HttpClient client = new HttpClient();
753            GetMethod get = new GetMethod(sbProcessUrl.toString());
754
755            get.addRequestHeader("Accept", "text/plain");
756
757            int result = client.executeMethod(get);
758            String slist = get.getResponseBodyAsString();
759
760            String[] s = slist.split("\n");
761            i = s.length - 1;
762        } catch (Exception e) {
763            e.printStackTrace();
764        }
765        return i;
766    }
767
768    public void onClick$btnAnimationStart(Event event) {
769        try {
770
771            Integer monthOrYear = 0; //0=month, 1=year
772
773            if("1".equals(cbAnimationDenomination.getValue()) || "Year".equalsIgnoreCase(cbAnimationDenomination.getValue())){
774                monthOrYear = 1;
775            }
776
777            System.out.println("Animation: " + monthOrYear);
778
779            Integer step = 1;
780            if(monthOrYear != 0){
781                step = intAnimationStep.getValue();
782                if(step < 1) {
783                    step = 1;
784                    intAnimationStep.setValue(1);
785                }
786            }
787            
788            Double interval = dblAnimationSeconds.getValue();
789            if(interval < 0.2) {
790                interval = 0.2;
791                dblAnimationSeconds.setValue(0.2);
792            }
793
794            mapLayer.setData("animation_step", step);
795            mapLayer.setData("animation_interval", interval);
796
797            Integer start = (Integer) intAnimationYearStart.getValue();
798            Integer end =  (Integer) intAnimationYearEnd.getValue();
799            String script = "mapFrame.animateStart('" + StringEscapeUtils.escapeJavaScript(mapLayer.getNameJS()) + "',"
800                        + monthOrYear + ","
801                        + interval * 1000 + ","
802                        + start + ","
803                        + end + ","
804                        + step + ");";
805            System.out.println("Script: " + script );
806
807            getMapComposer().getOpenLayersJavascript().execute(script);
808
809            btnAnimationStop.setDisabled(false);
810        } catch (Exception e) {
811            e.printStackTrace();
812        }
813    }
814
815    public void selectYearOrMonth() {
816        if("1".equals(cbAnimationDenomination.getValue()) || "Year".equals(cbAnimationDenomination.getValue())){
817            dAnimationStep.setVisible(true);
818            //lblAnimationLabel.setVisible(true);
819        } else {
820            dAnimationStep.setVisible(false);
821            //lblAnimationLabel.setVisible(false);
822        }
823    }
824
825    private void updateAnimationDiv() {
826        if(dblAnimationSeconds == null) {
827            return;
828        }
829        try {
830            Query q = (Query) mapLayer.getData("query");
831            if(q != null && q instanceof BiocacheQuery) {
832                Integer firstYear = (Integer) mapLayer.getData("first_year");
833                Integer lastYear =  (Integer) mapLayer.getData("last_year");
834                if(firstYear == null) {
835                    try {
836                        LegendObject lo = ((BiocacheQuery)q).getLegend("occurrence_year");
837                        if(lo != null && lo.getMinMax() != null) {
838                            firstYear = (int) lo.getMinMax()[0];
839                            lastYear = (int) lo.getMinMax()[1];
840                            mapLayer.setData("first_year", firstYear);
841                            mapLayer.setData("last_year", lastYear);
842                        }
843                    } catch (Exception e) {
844                        //this will fail if there are no records
845                    }
846                }
847
848                Integer step = (Integer) mapLayer.getData("animation_step");
849                if(step != null) {
850                    intAnimationStep.setValue(step);
851                }
852
853                Double interval = (Double) mapLayer.getData("animation_interval");
854                if(interval != null) {
855                    dblAnimationSeconds.setValue(interval);
856                }
857
858                if(firstYear < lastYear) {
859                    //lblAnimationLabel.setValue("years " + firstYear + " to " + lastYear);
860                    intAnimationYearStart.setValue(firstYear);
861                    intAnimationYearEnd.setValue(lastYear);
862                    divAnimation.setVisible(true);
863                }
864            }
865        } catch (Exception e) {
866            e.printStackTrace();
867        }
868    }
869
870    public void onClick$btnAnimationStop(Event event) {
871        String script = "mapFrame.animateStop('" + StringEscapeUtils.escapeJavaScript(mapLayer.getNameJS()) + "');";
872        getMapComposer().getOpenLayersJavascript().execute(script);
873        btnAnimationStop.setDisabled(true);
874    }
875}