0001: package net.refractions.udig.style.sld.editor;
0002:
0003: import java.awt.Color;
0004: import java.io.IOException;
0005: import java.text.MessageFormat;
0006: import java.util.ArrayList;
0007: import java.util.HashMap;
0008: import java.util.HashSet;
0009: import java.util.Iterator;
0010: import java.util.List;
0011: import java.util.Set;
0012:
0013: import net.refractions.udig.style.internal.StyleLayer;
0014: import net.refractions.udig.style.sld.ImageConstants;
0015: import net.refractions.udig.style.sld.Images;
0016: import net.refractions.udig.style.sld.SLDContent;
0017: import net.refractions.udig.style.sld.SLDPlugin;
0018: import net.refractions.udig.style.sld.editor.internal.BrewerPaletteLabelProvider;
0019: import net.refractions.udig.style.sld.editor.internal.StyleTreeContentProvider;
0020: import net.refractions.udig.style.sld.editor.internal.StyleTreeLabelProvider;
0021: import net.refractions.udig.style.sld.editor.internal.StyleTreeSorter;
0022: import net.refractions.udig.style.sld.internal.Messages;
0023: import net.refractions.udig.ui.DecoratorOverlayIcon;
0024: import net.refractions.udig.ui.ErrorManager;
0025: import net.refractions.udig.ui.PlatformGIS;
0026: import net.refractions.udig.ui.graphics.SLDs;
0027: import net.refractions.udig.ui.graphics.TableSettings;
0028: import net.refractions.udig.ui.graphics.TableUtils;
0029:
0030: import org.eclipse.core.runtime.IProgressMonitor;
0031: import org.eclipse.core.runtime.NullProgressMonitor;
0032: import org.eclipse.jface.resource.ImageDescriptor;
0033: import org.eclipse.jface.viewers.CellEditor;
0034: import org.eclipse.jface.viewers.ColorCellEditor;
0035: import org.eclipse.jface.viewers.ColumnWeightData;
0036: import org.eclipse.jface.viewers.ICellModifier;
0037: import org.eclipse.jface.viewers.ISelectionChangedListener;
0038: import org.eclipse.jface.viewers.IStructuredContentProvider;
0039: import org.eclipse.jface.viewers.SelectionChangedEvent;
0040: import org.eclipse.jface.viewers.StructuredSelection;
0041: import org.eclipse.jface.viewers.TableLayout;
0042: import org.eclipse.jface.viewers.TableViewer;
0043: import org.eclipse.jface.viewers.TextCellEditor;
0044: import org.eclipse.jface.viewers.TreeViewer;
0045: import org.eclipse.jface.viewers.Viewer;
0046: import org.eclipse.jface.viewers.ViewerFilter;
0047: import org.eclipse.jface.viewers.ViewerSorter;
0048: import org.eclipse.swt.SWT;
0049: import org.eclipse.swt.custom.BusyIndicator;
0050: import org.eclipse.swt.events.SelectionEvent;
0051: import org.eclipse.swt.events.SelectionListener;
0052: import org.eclipse.swt.graphics.Font;
0053: import org.eclipse.swt.graphics.Image;
0054: import org.eclipse.swt.graphics.RGB;
0055: import org.eclipse.swt.layout.GridData;
0056: import org.eclipse.swt.layout.GridLayout;
0057: import org.eclipse.swt.widgets.Button;
0058: import org.eclipse.swt.widgets.Combo;
0059: import org.eclipse.swt.widgets.Composite;
0060: import org.eclipse.swt.widgets.Control;
0061: import org.eclipse.swt.widgets.Display;
0062: import org.eclipse.swt.widgets.Label;
0063: import org.eclipse.swt.widgets.Table;
0064: import org.eclipse.swt.widgets.TableColumn;
0065: import org.eclipse.swt.widgets.Tree;
0066: import org.eclipse.swt.widgets.TreeColumn;
0067: import org.eclipse.swt.widgets.TreeItem;
0068: import org.geotools.brewer.color.BrewerPalette;
0069: import org.geotools.brewer.color.ColorBrewer;
0070: import org.geotools.brewer.color.PaletteSuitability;
0071: import org.geotools.brewer.color.SampleScheme;
0072: import org.geotools.brewer.color.StyleGenerator;
0073: import org.geotools.data.FeatureSource;
0074: import org.geotools.event.GTComponent;
0075: import org.geotools.event.GTEvent;
0076: import org.geotools.feature.AttributeType;
0077: import org.geotools.feature.FeatureCollection;
0078: import org.geotools.feature.FeatureType;
0079: import org.geotools.feature.GeometryAttributeType;
0080: import org.geotools.feature.type.NumericAttributeType;
0081: import org.geotools.feature.visitor.UniqueVisitor;
0082: import org.geotools.filter.Expression;
0083: import org.geotools.filter.ExpressionType;
0084: import org.geotools.filter.FilterFactory;
0085: import org.geotools.filter.FilterFactoryFinder;
0086: import org.geotools.filter.IllegalFilterException;
0087: import org.geotools.filter.MathExpression;
0088: import org.geotools.filter.function.ClassificationFunction;
0089: import org.geotools.filter.function.CustomClassifierFunction;
0090: import org.geotools.filter.function.EqualIntervalFunction;
0091: import org.geotools.filter.function.QuantileFunction;
0092: import org.geotools.filter.function.StandardDeviationFunction;
0093: import org.geotools.filter.function.UniqueIntervalFunction;
0094: import org.geotools.styling.FeatureTypeStyle;
0095: import org.geotools.styling.Fill;
0096: import org.geotools.styling.LineSymbolizer;
0097: import org.geotools.styling.PointSymbolizer;
0098: import org.geotools.styling.PolygonSymbolizer;
0099: import org.geotools.styling.Rule;
0100: import org.geotools.styling.Style;
0101: import org.geotools.styling.StyleBuilder;
0102: import org.geotools.styling.StyledLayerDescriptor;
0103: import org.geotools.styling.Symbolizer;
0104: import org.geotools.util.NullProgressListener;
0105: import org.geotools.util.ProgressListener;
0106:
0107: public class StyleThemePage extends StyleEditorPage {
0108:
0109: public static final int COMBO_ATTRIBUTES = 1;
0110: public static final int COMBO_CLASSES = 2;
0111: public static final int COMBO_BREAKTYPE = 3;
0112: public static final int COMBO_NORMALIZE = 4;
0113: public static final int COMBO_ELSE = 5;
0114: public static final int COMBO_PALETTES = 6;
0115: public static final int COMBO_OPACITY = 7;
0116:
0117: public static final int LABEL_PALETTES = 10;
0118: public static final int LABEL_SEPARATOR_BOTTOM = 12;
0119: public static final int LABEL_STATUSBAR = 13;
0120:
0121: public static final int LABEL_ICON_COLORBLIND = 14;
0122: public static final int LABEL_ICON_PHOTOCOPY = 15;
0123: public static final int LABEL_ICON_PROJECTOR = 16;
0124: public static final int LABEL_ICON_LCD = 17;
0125: public static final int LABEL_ICON_CRT = 18;
0126: public static final int LABEL_ICON_PRINT = 19;
0127:
0128: public static final int BUTTON_COLORBLIND = 20;
0129: public static final int BUTTON_PHOTOCOPY = 21;
0130: public static final int BUTTON_PROJECTOR = 22;
0131: public static final int BUTTON_LCD = 23;
0132: public static final int BUTTON_CRT = 24;
0133: public static final int BUTTON_PRINT = 25;
0134: public static final int BUTTON_REMOVE = 26;
0135:
0136: public static final int COMPOSITE_PARENT = 30;
0137: public static final int COMPOSITE_TOP = 31;
0138: public static final int COMPOSITE_MIDDLE = 32;
0139: public static final int COMPOSITE_BOTTOM = 33;
0140: public static final int COMPOSITE_BOTTOM_LEFT = 34;
0141: public static final int COMPOSITE_BOTTOM_RIGHT = 35;
0142:
0143: private HashMap<Integer, Control> pageControls = new HashMap<Integer, Control>();
0144: private List<String> numericAttr = new ArrayList<String>();
0145: double[] opacity;
0146:
0147: HashMap<Integer, String> controlNames = new HashMap<Integer, String>();
0148: HashMap<Integer, Integer> viewerQuality = new HashMap<Integer, Integer>();
0149: HashMap<String, Integer> uniqueCounts = new HashMap<String, Integer>();
0150:
0151: TableViewer paletteTable;
0152: ColorBrewer brewer;
0153: BrewerPalette customPalette = null;
0154: boolean reverseColours = false;
0155: StyleGenerator sg;
0156: TreeViewer treeViewer;
0157: AttributeType selectedAttributeType;
0158: AttributeType normalize;
0159: ClassificationFunction classifier;
0160: CustomClassifierFunction customBreak = null;
0161: TableSettings tableSettings;
0162: boolean elseSelection = true;
0163:
0164: FilterFactory ff;
0165: FeatureCollection collection;
0166: FeatureSource source;
0167: StyleBuilder sb;
0168:
0169: public StyleThemePage() {
0170: //create factories
0171: ff = FilterFactoryFinder.createFilterFactory();
0172: sb = new StyleBuilder(ff);
0173:
0174: //suitability icons
0175: controlNames.put(LABEL_ICON_COLORBLIND,
0176: Messages.StyleEditor_theme_suitability_colour);
0177: controlNames.put(LABEL_ICON_CRT,
0178: Messages.StyleEditor_theme_suitability_crt);
0179: controlNames.put(LABEL_ICON_LCD,
0180: Messages.StyleEditor_theme_suitability_lcd);
0181: controlNames.put(LABEL_ICON_PHOTOCOPY,
0182: Messages.StyleEditor_theme_suitability_pcopy);
0183: controlNames.put(LABEL_ICON_PRINT,
0184: Messages.StyleEditor_theme_suitability_print);
0185: controlNames.put(LABEL_ICON_PROJECTOR,
0186: Messages.StyleEditor_theme_suitability_proj);
0187:
0188: //suitability toggle buttons
0189: controlNames.put(BUTTON_COLORBLIND,
0190: Messages.StyleEditor_theme_suitability_colour);
0191: controlNames.put(BUTTON_CRT,
0192: Messages.StyleEditor_theme_suitability_crt);
0193: controlNames.put(BUTTON_LCD,
0194: Messages.StyleEditor_theme_suitability_lcd);
0195: controlNames.put(BUTTON_PHOTOCOPY,
0196: Messages.StyleEditor_theme_suitability_pcopy);
0197: controlNames.put(BUTTON_PRINT,
0198: Messages.StyleEditor_theme_suitability_print);
0199: controlNames.put(BUTTON_PROJECTOR,
0200: Messages.StyleEditor_theme_suitability_proj);
0201:
0202: //suitability icon - palette suitability lookup
0203: viewerQuality.put(PaletteSuitability.VIEWER_COLORBLIND,
0204: LABEL_ICON_COLORBLIND);
0205: viewerQuality
0206: .put(PaletteSuitability.VIEWER_CRT, LABEL_ICON_CRT);
0207: viewerQuality
0208: .put(PaletteSuitability.VIEWER_LCD, LABEL_ICON_LCD);
0209: viewerQuality.put(PaletteSuitability.VIEWER_PHOTOCOPY,
0210: LABEL_ICON_PHOTOCOPY);
0211: viewerQuality.put(PaletteSuitability.VIEWER_PRINT,
0212: LABEL_ICON_PRINT);
0213: viewerQuality.put(PaletteSuitability.VIEWER_PROJECTOR,
0214: LABEL_ICON_PROJECTOR);
0215: }
0216:
0217: public Button getButton(int widgetID) {
0218: return (Button) getControl(widgetID);
0219: }
0220:
0221: public Combo getCombo(int widgetID) {
0222: return (Combo) getControl(widgetID);
0223: }
0224:
0225: public Composite getComposite(int widgetID) {
0226: return (Composite) getControl(widgetID);
0227: }
0228:
0229: public Label getLabel(int widgetID) {
0230: return (Label) getControl(widgetID);
0231: }
0232:
0233: public GridData getLayoutData(int widgetID) {
0234: Object widget = getControl(widgetID);
0235: Object layout = null;
0236: if (widget instanceof Composite) {
0237: layout = ((Composite) widget).getLayoutData();
0238: }
0239: if (layout instanceof GridData)
0240: return (GridData) layout;
0241: else
0242: return new GridData(); //return empty, or throw exception (null)?
0243: }
0244:
0245: public Object getControl(int widgetID) {
0246: return pageControls.get(widgetID);
0247: }
0248:
0249: private boolean isNumber(String attributeType) {
0250: return numericAttr.contains(attributeType);
0251: }
0252:
0253: private boolean isNumber(AttributeType attributeType) {
0254: if (attributeType instanceof NumericAttributeType)
0255: return true;
0256: else
0257: return false;
0258: }
0259:
0260: @Override
0261: public boolean isValid() {
0262: return true;
0263: }
0264:
0265: public boolean okToLeave() {
0266: return true;
0267: }
0268:
0269: @Override
0270: public boolean performCancel() {
0271: return true;
0272: }
0273:
0274: public boolean performOk() {
0275: return true;
0276: }
0277:
0278: @Override
0279: public void dispose() {
0280: super .dispose();
0281: //collection.purge();
0282: collection = null;
0283: source = null;
0284: }
0285:
0286: @Override
0287: public String getErrorMessage() {
0288: return null;
0289: }
0290:
0291: public ColorBrewer getBrewer() {
0292: if (brewer == null) {
0293: createBrewer();
0294: }
0295: return brewer;
0296: }
0297:
0298: private void createToggleButton(Composite parent, int buttonId,
0299: Image image) {
0300: Button toggleButton = new Button(parent, SWT.TOGGLE);
0301: GridData gridData = new GridData(SWT.NONE, SWT.NONE, false,
0302: false);
0303: toggleButton.setLayoutData(gridData);
0304: toggleButton.setImage(image);
0305: toggleButton.setSelection(false);
0306: toggleButton
0307: .addSelectionListener(new SuitabilityToggleListener(
0308: buttonId));
0309: pageControls.put(buttonId, toggleButton);
0310: updateToggleTooltip(buttonId);
0311: }
0312:
0313: private void updateToggleTooltip(int buttonId) {
0314: Button toggle = getButton(buttonId);
0315: String tooltip;
0316: if (toggle.getSelection()) {
0317: tooltip = Messages.StyleEditor_theme_suitability_show;
0318: } else {
0319: tooltip = Messages.StyleEditor_theme_suitability_hide;
0320: }
0321: toggle.setToolTipText(tooltip
0322: + " " + controlNames.get(buttonId)); //$NON-NLS-1$
0323: }
0324:
0325: private void createSuitabilityIcon(Composite parent, int id,
0326: String tooltip, Image image) {
0327: Label suitabilityIcon = new Label(parent, SWT.NONE);
0328: GridData gridData = new GridData(SWT.NONE, SWT.NONE, false,
0329: false);
0330: suitabilityIcon.setLayoutData(gridData);
0331: suitabilityIcon.setImage(image);
0332: suitabilityIcon.setToolTipText(tooltip);
0333: pageControls.put(id, suitabilityIcon);
0334: }
0335:
0336: @Override
0337: public void createPageContent(Composite parent) {
0338: //create the featureCollection
0339: IProgressMonitor monitor = new NullProgressMonitor();
0340: try {
0341: source = getSelectedLayer().getResource(
0342: FeatureSource.class, monitor); //monitor
0343: if (source == null)
0344: return;
0345: collection = source.getFeatures();
0346: } catch (IOException e) {
0347: SLDPlugin
0348: .log(
0349: "StyleThemePage.createPageContent() failed to create FeatureCollection", e); //$NON-NLS-1$
0350: return;
0351: }
0352:
0353: //create the content
0354: pageControls.put(COMPOSITE_PARENT, parent);
0355: Font font = getShell().getFont();
0356:
0357: Composite compTop = new Composite(parent, SWT.NONE);
0358: compTop.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
0359: false));
0360: GridLayout layout = new GridLayout(5, false);
0361: layout.marginHeight = 0;
0362: layout.marginWidth = 0;
0363: compTop.setLayout(layout);
0364: compTop.setFont(font);
0365: pageControls.put(COMPOSITE_TOP, compTop);
0366:
0367: Label separator = new Label(parent, SWT.HORIZONTAL
0368: | SWT.SEPARATOR);
0369: GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
0370: separator.setLayoutData(gridData);
0371: separator.setFont(font);
0372:
0373: Composite compMiddle = new Composite(parent, SWT.NONE);
0374: compMiddle.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
0375: true));
0376: layout = new GridLayout(1, false);
0377: layout.marginHeight = 0;
0378: layout.marginWidth = 0;
0379: compMiddle.setLayout(layout);
0380: compMiddle.setFont(font);
0381: pageControls.put(COMPOSITE_MIDDLE, compMiddle);
0382:
0383: separator = new Label(parent, SWT.HORIZONTAL | SWT.SEPARATOR);
0384: gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
0385: separator.setLayoutData(gridData);
0386: separator.setVisible(false);
0387: separator.setFont(font);
0388: pageControls.put(LABEL_SEPARATOR_BOTTOM, separator);
0389:
0390: Composite compBottom = new Composite(parent, SWT.NONE);
0391: gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
0392: gridData.heightHint = 0;
0393: compBottom.setLayoutData(gridData);
0394: layout = new GridLayout(2, false);
0395: layout.marginHeight = 0;
0396: layout.marginWidth = 0;
0397: compBottom.setLayout(layout);
0398: compBottom.setVisible(false);
0399: compBottom.setFont(font);
0400: pageControls.put(COMPOSITE_BOTTOM, compBottom);
0401:
0402: //Labels
0403: Label attributesLabel = new Label(compTop, SWT.NONE);
0404: attributesLabel.setFont(font);
0405: attributesLabel.setText(Messages.StyleEditor_theme_attribute);
0406: gridData = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
0407: attributesLabel.setLayoutData(gridData);
0408:
0409: Label classesLabel = new Label(compTop, SWT.NONE);
0410: classesLabel.setFont(font);
0411: classesLabel.setText(Messages.StyleEditor_theme_classes);
0412: gridData = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
0413: classesLabel.setLayoutData(gridData);
0414:
0415: Label breaksLabel = new Label(compTop, SWT.NONE);
0416: breaksLabel.setFont(font);
0417: breaksLabel.setText(Messages.StyleEditor_theme_break);
0418: gridData = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
0419: breaksLabel.setLayoutData(gridData);
0420:
0421: Label normalizeLabel = new Label(compTop, SWT.LEFT);
0422: normalizeLabel.setFont(font);
0423: normalizeLabel.setText(Messages.StyleEditor_theme_normalize);
0424: gridData = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
0425: normalizeLabel.setLayoutData(gridData);
0426:
0427: Label elseLabel = new Label(compTop, SWT.LEFT);
0428: elseLabel.setFont(font);
0429: elseLabel.setText(Messages.StyleEditor_theme_else);
0430: gridData = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
0431: elseLabel.setLayoutData(gridData);
0432:
0433: //Combos
0434: Combo attributeCombo = new Combo(compTop, SWT.BORDER
0435: | SWT.READ_ONLY);
0436: pageControls.put(COMBO_ATTRIBUTES, attributeCombo);
0437: attributeCombo.setLayout(new GridLayout());
0438: gridData = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
0439: attributeCombo.setLayoutData(gridData);
0440: //populate the comboBox
0441: StyleLayer selectedLayer = getSelectedLayer();
0442: if (selectedLayer != null) {
0443: FeatureType featureType = selectedLayer.getSchema();
0444:
0445: if (featureType != null) {
0446: for (int i = 0; i < featureType.getAttributeCount(); i++) {
0447: AttributeType attributeType = featureType
0448: .getAttributeType(i);
0449: if (!(attributeType instanceof GeometryAttributeType)) { //don't include the geometry
0450: attributeCombo.add(attributeType.getName());
0451: if (isNumber(attributeType)) {
0452: numericAttr.add(attributeType.getName());
0453: }
0454: }
0455: }
0456: //select the first numeric attribute that isn't ID
0457: int index = -1;
0458: if (numericAttr.size() > 1) {
0459: if (numericAttr.get(0).equalsIgnoreCase("id")) { //$NON-NLS-1$
0460: index = attributeCombo.indexOf(numericAttr
0461: .get(1));
0462: } else {
0463: index = attributeCombo.indexOf(numericAttr
0464: .get(0));
0465: }
0466: } else if (numericAttr.size() == 1) {
0467: index = attributeCombo.indexOf(numericAttr.get(0));
0468: }
0469: if (index > -1)
0470: attributeCombo.select(index);
0471: if (attributeCombo.getSelectionIndex() == -1) {
0472: //we couldn't find a desirable attribute, just grab the first one
0473: if (featureType.getAttributeCount() > 0) {
0474: attributeCombo.select(0);
0475: }
0476: }
0477: }
0478: }
0479: attributeCombo.setVisibleItemCount(16);
0480: attributeCombo
0481: .addSelectionListener(new AttributeComboListener());
0482:
0483: Combo classesCombo = new Combo(compTop, SWT.BORDER
0484: | SWT.READ_ONLY);
0485: pageControls.put(COMBO_CLASSES, classesCombo);
0486: classesCombo.setLayout(new GridLayout(1, false));
0487: gridData = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
0488: classesCombo.setLayoutData(gridData);
0489: for (int i = 2; i < 13; i++) {
0490: Integer j = (Integer) i;
0491: classesCombo.add(j.toString());
0492: }
0493: classesCombo.select(3); //default is 5 classes
0494: classesCombo.setVisibleItemCount(16);
0495: classesCombo.addSelectionListener(new ClassesComboListener());
0496:
0497: Combo breaksCombo = new Combo(compTop, SWT.BORDER
0498: | SWT.READ_ONLY);
0499: pageControls.put(COMBO_BREAKTYPE, breaksCombo);
0500: breaksCombo.setLayout(new GridLayout(1, false));
0501: gridData = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
0502: breaksCombo.setLayoutData(gridData);
0503: updateBreaks();
0504: breaksCombo.addSelectionListener(new SimpleComboListener());
0505:
0506: Combo normalizeCombo = new Combo(compTop, SWT.BORDER
0507: | SWT.READ_ONLY);
0508: pageControls.put(COMBO_NORMALIZE, normalizeCombo);
0509: gridData = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
0510: normalizeCombo.setLayoutData(gridData);
0511: updateNormalize();
0512: normalizeCombo
0513: .setToolTipText(Messages.StyleEditor_theme_normalize_tip);
0514: normalizeCombo.setVisibleItemCount(10);
0515: normalizeCombo.addSelectionListener(new SimpleComboListener());
0516:
0517: Combo elseCombo = new Combo(compTop, SWT.BORDER | SWT.READ_ONLY);
0518: pageControls.put(COMBO_ELSE, elseCombo);
0519: elseCombo.setLayout(new GridLayout(1, false));
0520: gridData = new GridData(SWT.LEFT, SWT.DEFAULT, true, false);
0521: elseCombo.setLayoutData(gridData);
0522: elseCombo.add(Messages.StyleEditor_theme_else_hide);
0523: elseCombo.add(Messages.StyleEditor_theme_else_min);
0524: elseCombo.add(Messages.StyleEditor_theme_else_max);
0525: elseCombo.select(0);
0526: elseCombo.setToolTipText(Messages.StyleEditor_theme_else_tip);
0527: elseCombo.addSelectionListener(new ElseComboListener());
0528:
0529: Composite compMiddle2 = new Composite(compMiddle, SWT.NONE);
0530: compMiddle2.setLayoutData(new GridData(SWT.FILL, SWT.NONE,
0531: true, false));
0532: layout = new GridLayout(2, false);
0533: layout.marginHeight = 0;
0534: layout.marginWidth = 0;
0535: compMiddle2.setLayout(layout);
0536:
0537: Label palettesLabel = new Label(compMiddle2, SWT.LEFT);
0538: palettesLabel.setFont(font);
0539: palettesLabel.setText(Messages.StyleEditor_theme_palette);
0540: gridData = new GridData(SWT.LEFT, SWT.BOTTOM, true, false);
0541: palettesLabel.setLayoutData(gridData);
0542:
0543: Composite compMiddle3 = new Composite(compMiddle2, SWT.NONE);
0544: compMiddle3.setLayoutData(new GridData(SWT.RIGHT, SWT.NONE,
0545: true, false));
0546: layout = new GridLayout(3, false);
0547: layout.marginHeight = 0;
0548: layout.marginWidth = 0;
0549: compMiddle3.setLayout(layout);
0550:
0551: Label paletteFilterLabel = new Label(compMiddle3, SWT.LEFT);
0552: paletteFilterLabel.setFont(font);
0553: paletteFilterLabel.setText(Messages.StyleEditor_theme_show);
0554: gridData = new GridData(SWT.LEFT, SWT.FILL, false, true);
0555: gridData.verticalSpan = 2;
0556: paletteFilterLabel.setLayoutData(gridData);
0557:
0558: Combo paletteFilter = new Combo(compMiddle3, SWT.BORDER
0559: | SWT.READ_ONLY);
0560: pageControls.put(COMBO_PALETTES, paletteFilter);
0561: paletteFilter.add(Messages.StyleEditor_theme_palette_all, 0);
0562: paletteFilter.add(Messages.StyleEditor_theme_palette_num, 1);
0563: paletteFilter.add(Messages.StyleEditor_theme_palette_seq, 2);
0564: paletteFilter.add(Messages.StyleEditor_theme_palette_div, 3);
0565: paletteFilter.add(Messages.StyleEditor_theme_palette_cat, 4);
0566: paletteFilter.select(0);
0567: paletteFilter
0568: .setToolTipText(Messages.StyleEditor_theme_palette_tip);
0569: paletteFilter.addSelectionListener(new SelectionListener() {
0570:
0571: public void widgetSelected(SelectionEvent e) {
0572: paletteTable.refresh();
0573: }
0574:
0575: public void widgetDefaultSelected(SelectionEvent e) {
0576: widgetSelected(e);
0577: }
0578:
0579: });
0580:
0581: Composite compMiddle4 = new Composite(compMiddle3, SWT.NONE);
0582: compMiddle4.setLayoutData(new GridData(SWT.RIGHT, SWT.NONE,
0583: true, false));
0584: layout = new GridLayout(6, true);
0585: layout.marginHeight = 0;
0586: layout.marginWidth = 0;
0587: layout.horizontalSpacing = 0;
0588: compMiddle4.setLayout(layout);
0589:
0590: //toggle buttons
0591: createToggleButton(compMiddle4, BUTTON_COLORBLIND, Images
0592: .getDescriptor(ImageConstants.COLORBLIND_ICON)
0593: .createImage());
0594: createToggleButton(compMiddle4, BUTTON_CRT, Images
0595: .getDescriptor(ImageConstants.CRT_ICON).createImage());
0596: createToggleButton(compMiddle4, BUTTON_PROJECTOR, Images
0597: .getDescriptor(ImageConstants.PROJECTOR_ICON)
0598: .createImage());
0599: createToggleButton(compMiddle4, BUTTON_LCD, Images
0600: .getDescriptor(ImageConstants.LAPTOP_ICON)
0601: .createImage());
0602: createToggleButton(compMiddle4, BUTTON_PRINT, Images
0603: .getDescriptor(ImageConstants.PRINTER_ICON)
0604: .createImage());
0605: createToggleButton(compMiddle4, BUTTON_PHOTOCOPY, Images
0606: .getDescriptor(ImageConstants.PHOTOCOPY_ICON)
0607: .createImage());
0608:
0609: //list of matching palettes
0610: paletteTable = new TableViewer(new Table(compMiddle, SWT.BORDER
0611: | SWT.V_SCROLL | SWT.FULL_SELECTION));
0612: TableLayout tableLayout = new TableLayout();
0613: tableLayout.addColumnData(new ColumnWeightData(1, 20, false));
0614: TableColumn firstColumn = new TableColumn(paletteTable
0615: .getTable(), SWT.LEFT);
0616: firstColumn.setAlignment(SWT.LEFT);
0617: paletteTable.getTable().setLayout(tableLayout);
0618: gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
0619: gridData.horizontalSpan = 2;
0620: gridData.heightHint = 150;
0621: gridData.widthHint = 175;
0622: paletteTable.getControl().setLayoutData(gridData);
0623:
0624: paletteTable.setLabelProvider(new BrewerPaletteLabelProvider());
0625: paletteTable
0626: .setContentProvider(new IStructuredContentProvider() {
0627:
0628: public Object[] getElements(Object inputElement) {
0629: if (inputElement instanceof ArrayList) {
0630: ArrayList list = (ArrayList) inputElement;
0631: return list.toArray();
0632: } else if (inputElement instanceof ColorBrewer) {
0633: ColorBrewer brewer = (ColorBrewer) inputElement;
0634: int selection = getCombo(COMBO_PALETTES)
0635: .getSelectionIndex();
0636: if (selection == 0) //All
0637: return brewer
0638: .getPalettes(ColorBrewer.ALL);
0639: else if (selection == 1) //Numerical
0640: return brewer
0641: .getPalettes(ColorBrewer.SUITABLE_RANGED);
0642: else if (selection == 2) //Sequential
0643: return brewer
0644: .getPalettes(ColorBrewer.SEQUENTIAL);
0645: else if (selection == 3) //Diverging
0646: return brewer
0647: .getPalettes(ColorBrewer.DIVERGING);
0648: else if (selection == 4) //Categorical
0649: return brewer
0650: .getPalettes(ColorBrewer.SUITABLE_UNIQUE);
0651: else
0652: return brewer.getPalettes();
0653: } else {
0654: return new Object[0];
0655: }
0656: }
0657:
0658: public void dispose() {
0659: }
0660:
0661: public void inputChanged(Viewer viewer,
0662: Object oldInput, Object newInput) {
0663: }
0664: });
0665:
0666: paletteTable.addFilter(new ViewerFilter() {
0667:
0668: @Override
0669: public boolean select(Viewer viewer, Object parentElement,
0670: Object element) {
0671: if (element instanceof BrewerPalette) {
0672: BrewerPalette pal = (BrewerPalette) element;
0673: int numClasses = new Integer(
0674: getCombo(COMBO_CLASSES).getText())
0675: .intValue();
0676: if (pal.getMaxColors() < numClasses) {
0677: return false;
0678: }
0679: if (getButton(BUTTON_COLORBLIND).getSelection()) {
0680: if (pal.getPaletteSuitability().getSuitability(
0681: numClasses,
0682: PaletteSuitability.VIEWER_COLORBLIND) != PaletteSuitability.QUALITY_GOOD)
0683: return false;
0684: }
0685: if (getButton(BUTTON_CRT).getSelection()) {
0686: if (pal.getPaletteSuitability().getSuitability(
0687: numClasses,
0688: PaletteSuitability.VIEWER_CRT) != PaletteSuitability.QUALITY_GOOD)
0689: return false;
0690: }
0691: if (getButton(BUTTON_LCD).getSelection()) {
0692: if (pal.getPaletteSuitability().getSuitability(
0693: numClasses,
0694: PaletteSuitability.VIEWER_LCD) != PaletteSuitability.QUALITY_GOOD)
0695: return false;
0696: }
0697: if (getButton(BUTTON_PHOTOCOPY).getSelection()) {
0698: if (pal.getPaletteSuitability().getSuitability(
0699: numClasses,
0700: PaletteSuitability.VIEWER_PHOTOCOPY) != PaletteSuitability.QUALITY_GOOD)
0701: return false;
0702: }
0703: if (getButton(BUTTON_PRINT).getSelection()) {
0704: if (pal.getPaletteSuitability().getSuitability(
0705: numClasses,
0706: PaletteSuitability.VIEWER_PRINT) != PaletteSuitability.QUALITY_GOOD)
0707: return false;
0708: }
0709: if (getButton(BUTTON_PROJECTOR).getSelection()) {
0710: if (pal.getPaletteSuitability().getSuitability(
0711: numClasses,
0712: PaletteSuitability.VIEWER_PROJECTOR) != PaletteSuitability.QUALITY_GOOD)
0713: return false;
0714: }
0715: }
0716: return true;
0717: }
0718:
0719: });
0720: paletteTable.setSorter(new ViewerSorter() {
0721:
0722: @Override
0723: public int compare(Viewer viewer, Object e1, Object e2) {
0724: if (e1 instanceof BrewerPalette
0725: && e2 instanceof BrewerPalette) {
0726: BrewerPalette p1 = (BrewerPalette) e1;
0727: BrewerPalette p2 = (BrewerPalette) e2;
0728: //alphabetical by name
0729: return p1.getName().compareTo(p2.getName());
0730: //TODO: alternatives (colour hue?)
0731: } else
0732: return super .compare(viewer, e1, e2);
0733: }
0734:
0735: });
0736:
0737: paletteTable.setInput(getBrewer());
0738: paletteTable
0739: .addSelectionChangedListener(new PalettesListener());
0740:
0741: //Bottom composite
0742: Composite compBottomLeft = new Composite(compBottom, SWT.NONE);
0743: compBottomLeft.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
0744: true, false));
0745: layout = new GridLayout(1, false);
0746: layout.marginHeight = 0;
0747: layout.marginWidth = 0;
0748: compBottomLeft.setLayout(layout);
0749: pageControls.put(COMPOSITE_BOTTOM_LEFT, compBottomLeft);
0750:
0751: Composite compBottomLeftButtons = new Composite(compBottomLeft,
0752: SWT.NONE);
0753: compBottomLeftButtons.setLayoutData(new GridData(SWT.LEFT,
0754: SWT.FILL, false, false));
0755: layout = new GridLayout(4, true);
0756: layout.marginHeight = 0;
0757: layout.marginWidth = 0;
0758: compBottomLeftButtons.setLayout(layout);
0759:
0760: Label opacityLabel = new Label(compBottomLeftButtons, SWT.NONE);
0761: opacityLabel.setFont(font);
0762: opacityLabel.setText(Messages.StyleEditor_theme_opacity);
0763: gridData = new GridData(SWT.LEFT, SWT.DEFAULT, false, false);
0764: opacityLabel.setLayoutData(gridData);
0765:
0766: Combo opacityCombo = new Combo(compBottomLeftButtons,
0767: SWT.BORDER | SWT.READ_ONLY);
0768: pageControls.put(COMBO_OPACITY, opacityCombo);
0769: opacity = new double[11];
0770: for (int i = 0; i < 11; i++) {
0771: opacityCombo.add(Integer.toString(i * 10) + "%"); //$NON-NLS-1$
0772: opacity[i] = i / 10.0;
0773: }
0774: opacityCombo.select(5); //default 50%
0775: opacityCombo.setVisibleItemCount(8);
0776: opacityCombo.addSelectionListener(new SimpleComboListener());
0777:
0778: Button reverseButton = new Button(compBottomLeftButtons,
0779: SWT.RIGHT);
0780: reverseButton.setText(Messages.StyleEditor_theme_reverse);
0781: reverseButton.addSelectionListener(new SelectionListener() {
0782:
0783: public void widgetSelected(SelectionEvent e) {
0784: reverseColours = !reverseColours; //used by generateTheme to get things half right
0785: FeatureTypeStyle fts = getFTS();
0786: Rule[] rule = fts.getRules();
0787: for (int i = 0; i < (rule.length / 2); i++) {
0788: swapColours(rule[i], rule[rule.length - i - 1]);
0789: }
0790: treeViewer.refresh();
0791: }
0792:
0793: public void widgetDefaultSelected(SelectionEvent e) {
0794: widgetSelected(e);
0795: }
0796:
0797: });
0798:
0799: Button removeButton = new Button(compBottomLeftButtons,
0800: SWT.RIGHT);
0801: removeButton.setText(Messages.StyleEditor_theme_remove);
0802: removeButton.setEnabled(false);
0803: removeButton.addSelectionListener(new SelectionListener() {
0804:
0805: public void widgetSelected(SelectionEvent e) {
0806: StructuredSelection selection = (StructuredSelection) treeViewer
0807: .getSelection();
0808: if (selection.isEmpty())
0809: return;
0810: Rule rule = (Rule) selection.getFirstElement();
0811: if (removeRule(rule)) {
0812: treeViewer.refresh();
0813: } else {
0814: //freak out
0815: }
0816: }
0817:
0818: public void widgetDefaultSelected(SelectionEvent e) {
0819: widgetSelected(e);
0820: }
0821:
0822: });
0823: pageControls.put(BUTTON_REMOVE, removeButton);
0824:
0825: treeViewer = new TreeViewer(compBottomLeft, SWT.BORDER
0826: | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
0827: Tree treeTable = treeViewer.getTree();
0828: treeTable.setHeaderVisible(true);
0829: treeTable.setLinesVisible(true);
0830: gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
0831: gridData.widthHint = compBottomLeft.getBounds().x;
0832: gridData.heightHint = compBottomLeft.getBounds().y;
0833: treeTable.setLayoutData(gridData);
0834:
0835: TreeColumn colImage = new TreeColumn(treeTable, SWT.LEFT);
0836: colImage.setText(Messages.StyleEditor_theme_column_colour);
0837:
0838: TreeColumn colTitle = new TreeColumn(treeTable, SWT.LEFT);
0839: colTitle.setText(Messages.StyleEditor_theme_column_label);
0840:
0841: TreeColumn colExpr = new TreeColumn(treeTable, SWT.LEFT);
0842: colExpr.setText(Messages.StyleEditor_theme_column_expression);
0843:
0844: treeTable.layout();
0845:
0846: tableSettings = new TableSettings(treeTable);
0847: tableSettings.setColumnMin(0, 40);
0848: tableSettings.setColumnMin(1, 100);
0849: tableSettings.setColumnMin(0, 50);
0850:
0851: treeViewer.setLabelProvider(new StyleTreeLabelProvider());
0852: treeViewer.setSorter(new StyleTreeSorter());
0853: treeViewer.setContentProvider(new StyleTreeContentProvider());
0854:
0855: CellEditor[] editors = new CellEditor[3];
0856:
0857: //TODO: create a nicer color chooser
0858: CellEditor celledit0 = new ColorCellEditor(treeViewer.getTree());
0859: TextCellEditor celledit1 = new TextCellEditor(treeViewer
0860: .getTree());
0861: TextCellEditor celledit2 = new TextCellEditor(treeViewer
0862: .getTree());
0863: editors[0] = celledit0;
0864: editors[1] = celledit1;
0865: editors[2] = celledit2;
0866:
0867: treeViewer
0868: .addSelectionChangedListener(new ISelectionChangedListener() {
0869:
0870: public void selectionChanged(
0871: SelectionChangedEvent event) {
0872:
0873: if (((StructuredSelection) event.getSelection())
0874: .isEmpty()) {
0875: getButton(BUTTON_REMOVE).setEnabled(false);
0876: } else {
0877: getButton(BUTTON_REMOVE).setEnabled(true);
0878: }
0879:
0880: }
0881:
0882: });
0883:
0884: treeViewer.setCellModifier(new ICellModifier() {
0885:
0886: public boolean canModify(Object element, String property) {
0887: if (property.equals("styleExpr")) { //$NON-NLS-1$
0888: if (element instanceof Rule) {
0889: Rule rule = (Rule) element;
0890: if (rule.getName().startsWith("rule")) { //$NON-NLS-1$
0891: if (rule.hasElseFilter()) {
0892: return false;
0893: }
0894: return true;
0895: } else {
0896: return false;
0897: }
0898: }
0899: } else if (property.equals("title")) { //$NON-NLS-1$
0900: return true;
0901: } else if (property == "colour") { //$NON-NLS-1$
0902: return true;
0903: }
0904: return false;
0905: }
0906:
0907: public Object getValue(Object element, String property) {
0908: if (property.equals("styleExpr")) { //$NON-NLS-1$
0909: if (element instanceof Rule) {
0910: Rule rule = (Rule) element;
0911: if (rule.hasElseFilter()) {
0912: return "else"; //$NON-NLS-1$
0913: } else {
0914: return StyleGenerator
0915: .toStyleExpression(rule.getFilter());
0916: }
0917: }
0918: } else if (property.equals("title")) { //$NON-NLS-1$
0919: if (element instanceof Rule) {
0920: Rule rule = (Rule) element;
0921: //the title contains the same value, but we'll obtain it from the rule anyways
0922: return rule.getTitle();
0923: }
0924: } else if (property.equals("colour")) { //$NON-NLS-1$
0925: if (element instanceof Rule) {
0926: Rule rule = (Rule) element;
0927: Color colour = SLDs
0928: .toColor(SLDs.colors(rule)[0]);
0929: RGB rgb = new RGB(colour.getRed(), colour
0930: .getGreen(), colour.getBlue());
0931: return rgb;
0932: }
0933: }
0934:
0935: return new Object[0];
0936: }
0937:
0938: public void modify(Object element, String property,
0939: Object value) {
0940: if (property.equals("styleExpr")) { //$NON-NLS-1$
0941: if (element instanceof TreeItem) {
0942: String newExpr = (String) value;
0943: TreeItem item = (TreeItem) element;
0944: Object data = item.getData();
0945: //create/modify the custom break and regen
0946: customBreak = new CustomClassifierFunction();
0947: //TODO: set expression?
0948: //figure out which rule has changed
0949: int ruleIndex = Integer.parseInt(((Rule) data)
0950: .getName().substring(4)) - 1;
0951: //fill the custom classifier with the rule boundary values
0952: Rule[] rules = getFTS().getRules();
0953: for (int i = 0; i < rules.length; i++) {
0954: String this Expr;
0955: if (i == ruleIndex) { //use the new value
0956: this Expr = newExpr;
0957: } else { //use the fts value
0958: if (rules[i].getFilter() == null) {
0959: this Expr = null; //probably an else filter
0960: } else {
0961: this Expr = StyleGenerator
0962: .toStyleExpression(rules[i]
0963: .getFilter());
0964: }
0965: }
0966: if (this Expr == null) {
0967: //TODO: mark as "else"
0968: } else if (StyleGenerator
0969: .isRanged(this Expr)) {
0970: String[] minMax = this Expr
0971: .split("\\.\\."); //$NON-NLS-1$
0972: Double min = new Double(minMax[0]);
0973: Double max = new Double(minMax[1]);
0974: customBreak
0975: .setRangedValues(i, min, max);
0976: } else {
0977: String[] values = this Expr.split(", "); //$NON-NLS-1$
0978: for (int j = 0; j < values.length; j++) {
0979: customBreak.setExplicitValues(i,
0980: values[j]);
0981: }
0982: }
0983: }
0984: Combo breaks = getCombo(COMBO_BREAKTYPE);
0985: String[] allBreaks = breaks.getItems();
0986: int hasCustom = -1;
0987: for (int i = 0; i < allBreaks.length; i++) {
0988: if (allBreaks[i]
0989: .equalsIgnoreCase(Messages.StyleEditor_theme_custom)) {
0990: hasCustom = i;
0991: break;
0992: }
0993: }
0994: if (hasCustom > -1) {
0995: breaks.select(hasCustom);
0996: } else {
0997: breaks
0998: .add(Messages.StyleEditor_theme_custom);
0999: breaks.select(allBreaks.length);
1000: }
1001: if (inputsValid())
1002: generateTheme();
1003: //old method: update the fts
1004: // int index = item.getParent().indexOf(item);
1005: // //TODO: check that style conforms to our standard
1006: // FeatureTypeStyle fts = getFTS();
1007: // try {
1008: // StyleGenerator.modifyFTS(fts, index, (String) value);
1009: // } catch (IllegalFilterException e) {
1010: // // TODO Handle IllegalFilterException
1011: // throw new RuntimeException(e.getMessage());
1012: // }
1013: // treeViewer.setInput(fts);
1014: }
1015: } else if (property.equals("title")) { //$NON-NLS-1$
1016: if (element instanceof TreeItem) {
1017: TreeItem item = (TreeItem) element;
1018: Object data = item.getData();
1019: if (data instanceof Rule) {
1020: Rule rule = (Rule) data;
1021: if (rule.getTitle().equals(value))
1022: return; //don't bother -- value is the same
1023: rule.setTitle(value.toString());
1024: }
1025: treeViewer.refresh();
1026: }
1027: } else if (property.equals("colour")) { //$NON-NLS-1$
1028: if (value == null)
1029: return;
1030: if (element instanceof TreeItem) {
1031: TreeItem item = (TreeItem) element;
1032: Object data = item.getData();
1033: Expression newColorExpr = null;
1034: Expression oldColorExpr = null;
1035: Color newColor = null;
1036: StyleBuilder sb = new StyleBuilder();
1037: if (value instanceof RGB) {
1038: RGB rgb = (RGB) value;
1039: newColor = new Color(rgb.red, rgb.green,
1040: rgb.blue);
1041: String htmlColor = SLDs
1042: .toHTMLColor(newColor);
1043: newColorExpr = sb
1044: .literalExpression(htmlColor);
1045: }
1046: if (data instanceof Rule) {
1047: Rule rule = (Rule) data;
1048: Symbolizer[] symb = rule.getSymbolizers();
1049: if (symb.length == 1) { //we're only expecting 1
1050: if (symb[0] instanceof PolygonSymbolizer) {
1051: PolygonSymbolizer ps = (PolygonSymbolizer) symb[0];
1052: Fill fill = ps.getFill();
1053: oldColorExpr = fill.getColor();
1054: if (oldColorExpr
1055: .equals(newColorExpr)) {
1056: return; //don't bother, same colour
1057: }
1058: //determine if the palette is already customized
1059: if (customPalette == null) {
1060: int numClasses = new Integer(
1061: getCombo(COMBO_CLASSES)
1062: .getItem(
1063: getCombo(
1064: COMBO_CLASSES)
1065: .getSelectionIndex()))
1066: .intValue();
1067: //create the palette from the current one
1068: BrewerPalette pal = (BrewerPalette) ((StructuredSelection) paletteTable
1069: .getSelection())
1070: .getFirstElement();
1071: customPalette = new BrewerPalette();
1072: PaletteSuitability suitability = new PaletteSuitability();
1073: //suitability.
1074: //customPalette.setColors()
1075: SampleScheme newScheme = new SampleScheme();
1076: Color[] colors = new Color[pal
1077: .getMaxColors()];
1078: Color[] allColorsArray = pal
1079: .getColors();
1080: List<Color> allColors = new ArrayList<Color>();
1081: for (int i = 0; i < allColorsArray.length; i++) {
1082: allColors
1083: .add(allColorsArray[i]);
1084: }
1085: String unknown = "?"; //$NON-NLS-1$
1086: for (int i = 0; i < pal
1087: .getMaxColors(); i++) {
1088: if (i > 0) {
1089: //create a simple scheme
1090: int[] scheme = new int[i + 1];
1091: for (int j = 0; j < i + 1; j++) {
1092: scheme[j] = j;
1093: }
1094: newScheme
1095: .setSampleScheme(
1096: i + 1,
1097: scheme);
1098: //set the suitability to unknown
1099: try {
1100: suitability
1101: .setSuitability(
1102: i + 1,
1103: new String[] {
1104: unknown,
1105: unknown,
1106: unknown,
1107: unknown,
1108: unknown,
1109: unknown });
1110: } catch (IOException e) {
1111: SLDPlugin
1112: .log(
1113: "setSuitability() failed", e); //$NON-NLS-1$
1114: return;
1115: }
1116: }
1117: //copy the color
1118: if (i < numClasses) {
1119: //copy the colors directly over
1120: colors[i] = pal
1121: .getColor(i,
1122: numClasses);
1123: allColors
1124: .remove(colors[i]);
1125: } else {
1126: //find unique colors to fill in the rest of the palette
1127: colors[i] = allColors
1128: .remove(0);
1129: }
1130: }
1131: //newScheme.setSampleScheme(3, new int[] {0,1});
1132: customPalette
1133: .setPaletteSuitability(suitability);
1134: customPalette.setColors(colors);
1135: customPalette
1136: .setColorScheme(newScheme);
1137: customPalette
1138: .setName(Messages.StyleEditor_theme_custom);
1139: customPalette
1140: .setDescription(Messages.StyleEditor_theme_custom_desc);
1141: customPalette.setType(pal
1142: .getType());
1143: if (!getBrewer()
1144: .hasPalette(
1145: Messages.StyleEditor_theme_custom)) {
1146: getBrewer()
1147: .registerPalette(
1148: customPalette);
1149: }
1150: }
1151: //seek and destroy the old colour
1152: Color[] colors = customPalette
1153: .getColors();
1154: int expectedIndex = -1;
1155: if (rule.getName().toLowerCase()
1156: .startsWith("rule")) { //$NON-NLS-1$
1157: expectedIndex = Integer
1158: .parseInt(rule
1159: .getName()
1160: .substring(4)) - 1;
1161: }
1162: int actualIndex = -1;
1163: for (int i = 0; i < colors.length; i++) {
1164: if (oldColorExpr
1165: .equals(sb
1166: .literalExpression(SLDs
1167: .toHTMLColor(colors[i])))) {
1168: actualIndex = i;
1169: if (expectedIndex == i) {
1170: //we found the correct old color where we expected to
1171: break;
1172: } //otherwise, keep looking just in case
1173: }
1174: }
1175: if (actualIndex == -1) {
1176: SLDPlugin
1177: .log(
1178: "color match unsuccessful... " + oldColorExpr + " vs " + newColorExpr, null); //$NON-NLS-1$ //$NON-NLS-2$
1179: //TODO: use different colour matching technique
1180: return;
1181: }
1182: colors[actualIndex] = newColor;
1183: customPalette.setColors(colors);
1184: paletteTable.setInput(getBrewer());
1185: paletteTable
1186: .setSelection(new StructuredSelection(
1187: customPalette));
1188: }
1189: }
1190: }
1191: treeViewer.refresh();
1192: }
1193: }
1194:
1195: }
1196: });
1197: treeViewer.setColumnProperties(new String[] {
1198: "colour", "title", "styleExpr" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1199: treeViewer.setCellEditors(editors);
1200: //populate the tree
1201: treeViewer.setInput(getFTS());
1202: treeViewer.expandAll();
1203: Control treeControl = treeViewer.getControl();
1204: GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
1205: gd.horizontalSpan = 2;
1206: treeControl.setLayoutData(gd);
1207: treeControl.setFont(font);
1208: treeControl.setVisible(false);
1209:
1210: Composite compBottomRight = new Composite(compBottom, SWT.NONE);
1211: compBottomRight.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL,
1212: false, false));
1213: layout = new GridLayout(1, false);
1214: layout.marginHeight = 0;
1215: layout.marginWidth = 0;
1216: compBottomRight.setLayout(layout);
1217:
1218: Label labelSuitability = new Label(compBottomRight, SWT.NONE);
1219: labelSuitability.setLayoutData(new GridData(SWT.NONE, SWT.NONE,
1220: false, false));
1221: labelSuitability
1222: .setText(Messages.StyleEditor_theme_suitability);
1223:
1224: Composite icons = new Composite(compBottomRight, SWT.RIGHT);
1225: icons.setLayoutData(new GridData(SWT.RIGHT, SWT.NONE, false,
1226: false));
1227: layout = new GridLayout(3, true);
1228: layout.marginHeight = 0;
1229: layout.marginWidth = 0;
1230: icons.setLayout(layout);
1231:
1232: createSuitabilityIcon(icons, LABEL_ICON_COLORBLIND,
1233: Messages.StyleEditor_theme_suitability_colour, Images
1234: .getDescriptor(ImageConstants.COLORBLIND_ICON)
1235: .createImage());
1236: createSuitabilityIcon(icons, LABEL_ICON_CRT,
1237: Messages.StyleEditor_theme_suitability_crt, Images
1238: .getDescriptor(ImageConstants.CRT_ICON)
1239: .createImage());
1240: createSuitabilityIcon(icons, LABEL_ICON_PROJECTOR,
1241: Messages.StyleEditor_theme_suitability_proj, Images
1242: .getDescriptor(ImageConstants.PROJECTOR_ICON)
1243: .createImage());
1244: createSuitabilityIcon(icons, LABEL_ICON_LCD,
1245: Messages.StyleEditor_theme_suitability_lcd, Images
1246: .getDescriptor(ImageConstants.LAPTOP_ICON)
1247: .createImage());
1248: createSuitabilityIcon(icons, LABEL_ICON_PRINT,
1249: Messages.StyleEditor_theme_suitability_print, Images
1250: .getDescriptor(ImageConstants.PRINTER_ICON)
1251: .createImage());
1252: createSuitabilityIcon(icons, LABEL_ICON_PHOTOCOPY,
1253: Messages.StyleEditor_theme_suitability_pcopy, Images
1254: .getDescriptor(ImageConstants.PHOTOCOPY_ICON)
1255: .createImage());
1256:
1257: //create status bar
1258: Label status = new Label(parent, SWT.NONE);
1259: gridData = new GridData(SWT.FILL, SWT.BOTTOM, true, false);
1260: status.setLayoutData(gridData);
1261: status.setVisible(true);
1262: status.setFont(font);
1263: status.setText(""); //$NON-NLS-1$
1264: pageControls.put(LABEL_STATUSBAR, status);
1265: }
1266:
1267: private boolean removeRule(Rule rule) {
1268: //find the FTS containing the rule
1269: GTComponent parent = rule.getNote().getParent();
1270: if (!(parent instanceof FeatureTypeStyle)) {
1271: return false;
1272: }
1273: FeatureTypeStyle fts = (FeatureTypeStyle) parent;
1274: Rule[] rules = fts.getRules();
1275: boolean found = false;
1276: int index = 0;
1277: for (index = 0; index < rules.length; index++) {
1278: if (rules[index] == rule) {
1279: found = true;
1280: break;
1281: }
1282: }
1283: if (!found)
1284: return false;
1285: Object[] result = removeElement(rules, index);
1286: Rule[] newRules = new Rule[result.length];
1287: for (int i = 0; i < newRules.length; i++) {
1288: newRules[i] = (Rule) result[i];
1289: }
1290: fts.setRules(newRules);
1291: return true;
1292: }
1293:
1294: private void swapColours(Rule rule1, Rule rule2) {
1295: Symbolizer[] symb1 = rule1.getSymbolizers();
1296: Symbolizer[] symb2 = rule2.getSymbolizers();
1297: if (symb1.length != symb2.length) {
1298: SLDPlugin
1299: .log(
1300: "StyleThemePage.swapColours(): Number of symbolizers each rule and not equal - aborting colour swap", null); //$NON-NLS-1$
1301: return;
1302: }
1303: Expression tempColour;
1304: for (int i = 0; i < symb1.length; i++) {
1305: if (symb1[i] instanceof PolygonSymbolizer) {
1306: tempColour = ((PolygonSymbolizer) symb1[i]).getFill()
1307: .getColor();
1308: ((PolygonSymbolizer) symb1[i]).getFill().setColor(
1309: ((PolygonSymbolizer) symb2[i]).getFill()
1310: .getColor());
1311: ((PolygonSymbolizer) symb2[i]).getFill().setColor(
1312: tempColour);
1313: } else if (symb1[i] instanceof PointSymbolizer) {
1314: tempColour = ((PointSymbolizer) symb1[i]).getGraphic()
1315: .getMarks()[0].getFill().getColor();
1316: ((PointSymbolizer) symb1[i]).getGraphic().getMarks()[0]
1317: .getFill().setColor(
1318: ((PointSymbolizer) symb2[i])
1319: .getGraphic().getMarks()[0]
1320: .getFill().getColor());
1321: ((PointSymbolizer) symb2[i]).getGraphic().getMarks()[0]
1322: .getFill().setColor(tempColour);
1323: } else if (symb1[i] instanceof LineSymbolizer) {
1324: tempColour = ((LineSymbolizer) symb1[i]).getStroke()
1325: .getColor();
1326: ((LineSymbolizer) symb1[i]).getStroke().setColor(
1327: ((LineSymbolizer) symb2[i]).getStroke()
1328: .getColor());
1329: ((LineSymbolizer) symb2[i]).getStroke().setColor(
1330: tempColour);
1331: }
1332: }
1333: }
1334:
1335: public void setStatusText(String text) {
1336: getLabel(LABEL_STATUSBAR).setText(text);
1337: }
1338:
1339: @Override
1340: public String getLabel() {
1341: return null;
1342: }
1343:
1344: private class AttributeComboListener implements SelectionListener {
1345: public void widgetSelected(SelectionEvent e) {
1346: //record the attribute
1347: selectedAttributeType = getAttributeType(getCombo(
1348: COMBO_ATTRIBUTES).getText());
1349: //update the normalization combo
1350: updateNormalize();
1351: //update the classification type (breaks) combo
1352: updateBreaks();
1353: if (isNumber(selectedAttributeType)) {
1354: //clear the status label
1355: setStatusText(""); //$NON-NLS-1$
1356: } else {
1357: //TODO: don't use strings to match break types
1358: if (getCombo(COMBO_BREAKTYPE).getText()
1359: .equalsIgnoreCase(
1360: Messages.StyleEditor_theme_uniques)) {
1361: //determine if we've already calculated the number of unique values
1362: String attribute = selectedAttributeType.getName();
1363: if (uniqueCounts.containsKey(attribute)) {
1364: updateUnique(attribute, uniqueCounts
1365: .get(attribute));
1366: }
1367: //count the number of unique attributes
1368: int uniqueCount = -1;
1369: try {
1370: Expression attr = ff
1371: .createAttributeExpression(attribute);
1372: UniqueVisitor uniques = new UniqueVisitor(attr);
1373: ProgressListener progress = new NullProgressListener();
1374: collection.accepts(uniques, progress);
1375: uniqueCount = uniques.getUnique().size();
1376: } catch (IOException e1) {
1377: SLDPlugin.log(
1378: "unique values calculation failed", e1); //$NON-NLS-1$
1379: }
1380: if (uniqueCount > -1) {
1381: updateUnique(attribute, uniqueCount);
1382: }
1383: } else {
1384: //clear the status label
1385: setStatusText(""); //$NON-NLS-1$
1386: }
1387: }
1388:
1389: //calculate the color scheme, if we have enough information
1390: if (inputsValid())
1391: generateTheme();
1392: return;
1393: }
1394:
1395: public void widgetDefaultSelected(SelectionEvent e) {
1396: widgetSelected(e);
1397: }
1398:
1399: private void updateUnique(String attr, int uniqueCount) {
1400: setStatusText(MessageFormat.format(
1401: Messages.StyleEditor_theme_unique_values,
1402: uniqueCount, attr));
1403: if (uniqueCount < 12) {
1404: if (getCombo(COMBO_ELSE).getSelectionIndex() > 0) {
1405: getCombo(COMBO_CLASSES).select(uniqueCount - 1);
1406: } else {
1407: getCombo(COMBO_CLASSES).select(uniqueCount - 2);
1408: }
1409: } else if (uniqueCount == 12) {
1410: getCombo(COMBO_CLASSES).select(10);
1411: }
1412: }
1413: }
1414:
1415: private class PalettesListener implements ISelectionChangedListener {
1416:
1417: public void selectionChanged(SelectionChangedEvent event) {
1418: if (inputsValid())
1419: generateTheme();
1420: }
1421:
1422: }
1423:
1424: private class SuitabilityToggleListener implements
1425: SelectionListener {
1426: private int id;
1427:
1428: public SuitabilityToggleListener(int id) {
1429: super ();
1430: this .id = id;
1431: }
1432:
1433: public void widgetSelected(SelectionEvent e) {
1434: System.out.println(e.getSource());
1435: updateToggleTooltip(id);
1436: updatePalettes();
1437: }
1438:
1439: public void widgetDefaultSelected(SelectionEvent e) {
1440: widgetSelected(e);
1441: }
1442:
1443: }
1444:
1445: private class ClassesComboListener implements SelectionListener {
1446: public void widgetSelected(SelectionEvent e) {
1447: updatePalettes();
1448: if (inputsValid())
1449: generateTheme();
1450: return;
1451: }
1452:
1453: public void widgetDefaultSelected(SelectionEvent e) {
1454: widgetSelected(e);
1455: }
1456:
1457: }
1458:
1459: private class ElseComboListener implements SelectionListener {
1460: public void widgetSelected(SelectionEvent e) {
1461: int index = getCombo(COMBO_ELSE).getSelectionIndex();
1462: int classesIndex = getCombo(COMBO_CLASSES)
1463: .getSelectionIndex();
1464: if (elseSelection && index == 0) { //else rule was turned off
1465: if (classesIndex > 0) {
1466: getCombo(COMBO_CLASSES).select(classesIndex - 1);
1467: }
1468: } else if (!elseSelection && index != 0) { //else rule was turned on
1469: if (classesIndex < (getCombo(COMBO_CLASSES)
1470: .getItemCount() - 1)) {
1471: getCombo(COMBO_CLASSES).select(classesIndex + 1);
1472: }
1473: }
1474: elseSelection = (index > 0);
1475: if (inputsValid())
1476: generateTheme();
1477: }
1478:
1479: public void widgetDefaultSelected(SelectionEvent e) {
1480: widgetSelected(e);
1481: }
1482: }
1483:
1484: private class SimpleComboListener implements SelectionListener {
1485: public void widgetSelected(SelectionEvent e) {
1486: if (inputsValid())
1487: generateTheme();
1488: }
1489:
1490: public void widgetDefaultSelected(SelectionEvent e) {
1491: widgetSelected(e);
1492: }
1493: }
1494:
1495: private void updatePalettes() {
1496: paletteTable.setInput(getBrewer());
1497: }
1498:
1499: private void updateBreaks() {
1500: Combo breaksCombo = getCombo(COMBO_BREAKTYPE);
1501: String currentAttr = getCombo(COMBO_ATTRIBUTES).getText();
1502: String value = breaksCombo.getText();
1503: breaksCombo.removeAll();
1504: if (isNumber(currentAttr)) { //show numeric break types
1505: breaksCombo.add(Messages.StyleEditor_theme_equalInterval);
1506: breaksCombo.add(Messages.StyleEditor_theme_quantile);
1507: //breaksCombo.add(Messages.StyleEditor_theme_standardDeviation);
1508: int index = breaksCombo.indexOf(value);
1509: if (index > -1)
1510: breaksCombo.select(index);
1511: else
1512: breaksCombo.select(1);
1513: } else { //show categorical break types
1514: breaksCombo.add(Messages.StyleEditor_theme_uniques);
1515: int index = breaksCombo.indexOf(value);
1516: if (index > -1)
1517: breaksCombo.select(index);
1518: else
1519: breaksCombo.select(0);
1520: }
1521: }
1522:
1523: private void updateNormalize() {
1524: Combo normalizeCombo = getCombo(COMBO_NORMALIZE);
1525: String value = normalizeCombo.getText();
1526: String currentAttr = getCombo(COMBO_ATTRIBUTES).getText();
1527: normalizeCombo.removeAll();
1528: normalizeCombo.add(Messages.StyleEditor_theme_none);
1529: if (isNumber(currentAttr)) {
1530: normalizeCombo.setEnabled(true);
1531: for (int i = 0; i < numericAttr.size(); i++) {
1532: String attr = numericAttr.get(i);
1533: if (!currentAttr.equals(attr))
1534: normalizeCombo.add(attr);
1535: }
1536: int index = normalizeCombo.indexOf(value);
1537: if (index > 1)
1538: normalizeCombo.select(index);
1539: else
1540: normalizeCombo.select(0); //default is "< NONE >"
1541: } else {
1542: normalizeCombo.select(0);
1543: normalizeCombo.setEnabled(false);
1544: }
1545: }
1546:
1547: private boolean inputsValid() {
1548: if (getCombo(COMBO_ATTRIBUTES).getText().length() < 1)
1549: return false;
1550: else if (paletteTable.getSelection().isEmpty())
1551: return false;
1552: else if (getCombo(COMBO_CLASSES).getText().length() < 1)
1553: return false;
1554: else
1555: return true;
1556: }
1557:
1558: private void generateTheme() {
1559: if (selectedAttributeType == null) {
1560: selectedAttributeType = getAttributeType(getCombo(
1561: COMBO_ATTRIBUTES).getText());
1562: }
1563: if (getCombo(COMBO_NORMALIZE).getSelectionIndex() == 0) {
1564: normalize = null;
1565: } else {
1566: normalize = getAttributeType(getCombo(COMBO_NORMALIZE)
1567: .getText());
1568: }
1569:
1570: //change the close button to cancel
1571: ((StyleEditorDialog) getContainer()).setCancelMode(true);
1572:
1573: //generate the defaults
1574: Runnable genDefault = new Runnable() {
1575: public void run() {
1576: //generate the expression
1577: Expression expr;
1578: try {
1579: Expression attr = ff
1580: .createAttributeExpression(selectedAttributeType
1581: .getName());
1582: if (normalize != null) {
1583: MathExpression divide = ff
1584: .createMathExpression(ExpressionType.MATH_DIVIDE);
1585: divide.addLeftValue(attr);
1586: divide.addRightValue(ff
1587: .createAttributeExpression(normalize
1588: .getName()));
1589: expr = divide;
1590: } else {
1591: expr = attr;
1592: }
1593: } catch (IllegalFilterException e) {
1594: // TODO Handle IllegalFilterException
1595: throw (RuntimeException) new RuntimeException()
1596: .initCause(e);
1597: }
1598: BrewerPalette pal = (BrewerPalette) ((StructuredSelection) paletteTable
1599: .getSelection()).getFirstElement();
1600: String paletteName = pal.getName();
1601: int numClasses = new Integer(getCombo(COMBO_CLASSES)
1602: .getItem(
1603: getCombo(COMBO_CLASSES)
1604: .getSelectionIndex()))
1605: .intValue();
1606: int[] suitability = pal.getPaletteSuitability()
1607: .getSuitability(numClasses);
1608:
1609: //check for custom classifier
1610: if (getCombo(COMBO_BREAKTYPE).getText()
1611: .equalsIgnoreCase(
1612: Messages.StyleEditor_theme_custom)) {
1613: classifier = customBreak;
1614: }
1615:
1616: boolean classifierModified = false;
1617: if (classifier == null) {
1618: classifierModified = true;
1619: } else {
1620: //determine if the classifier needs recalculation
1621: if (classifier.getNumberOfClasses() != new Integer(
1622: getCombo(COMBO_CLASSES).getText())
1623: .intValue()) {
1624: if (getCombo(COMBO_ELSE).getSelectionIndex() == 0)
1625: classifierModified = true;
1626: if (classifier.getNumberOfClasses() != new Integer(
1627: getCombo(COMBO_CLASSES).getText())
1628: .intValue() - 1)
1629: classifierModified = true;
1630: }
1631: if (getCombo(COMBO_ELSE).getSelectionIndex() > 0)
1632: classifierModified = true;
1633: else if (getCombo(COMBO_BREAKTYPE).getText()
1634: .equalsIgnoreCase(
1635: Messages.StyleEditor_theme_custom))
1636: classifierModified = true;
1637: else if ((getCombo(COMBO_BREAKTYPE).getText()
1638: .equalsIgnoreCase(Messages.StyleEditor_theme_equalInterval))
1639: && !(classifier instanceof EqualIntervalFunction))
1640: classifierModified = true;
1641: else if ((getCombo(COMBO_BREAKTYPE).getText()
1642: .equalsIgnoreCase(Messages.StyleEditor_theme_quantile))
1643: && !(classifier instanceof QuantileFunction))
1644: classifierModified = true;
1645: else if ((getCombo(COMBO_BREAKTYPE).getText()
1646: .equalsIgnoreCase(Messages.StyleEditor_theme_standardDeviation))
1647: && !(classifier instanceof StandardDeviationFunction))
1648: classifierModified = true;
1649: else if (!classifier.getExpression().equals(expr))
1650: classifierModified = true;
1651: }
1652:
1653: String semanticTypeIdentifier;
1654: //break type:palette
1655: if (getCombo(COMBO_BREAKTYPE).getText()
1656: .equalsIgnoreCase(
1657: Messages.StyleEditor_theme_uniques))
1658: semanticTypeIdentifier = "unique:"; //$NON-NLS-1$
1659: else if (getCombo(COMBO_BREAKTYPE)
1660: .getText()
1661: .equalsIgnoreCase(
1662: Messages.StyleEditor_theme_equalInterval))
1663: semanticTypeIdentifier = "equalinterval:"; //$NON-NLS-1$
1664: else if (getCombo(COMBO_BREAKTYPE).getText()
1665: .equalsIgnoreCase(
1666: Messages.StyleEditor_theme_quantile))
1667: semanticTypeIdentifier = "quantile:"; //$NON-NLS-1$
1668: else if (getCombo(COMBO_BREAKTYPE).getText()
1669: .equalsIgnoreCase("standard deviation")) //$NON-NLS-1$
1670: semanticTypeIdentifier = "standarddeviation:"; //$NON-NLS-1$
1671: else if (getCombo(COMBO_BREAKTYPE).getText()
1672: .equalsIgnoreCase(
1673: Messages.StyleEditor_theme_custom))
1674: semanticTypeIdentifier = "custom:"; //$NON-NLS-1$
1675: else {
1676: semanticTypeIdentifier = "default:"; //$NON-NLS-1$
1677: }
1678: semanticTypeIdentifier = semanticTypeIdentifier
1679: .concat(paletteName.toLowerCase());
1680:
1681: //create the classification function, if necessary
1682: if (classifierModified) {
1683: //TODO: add other classifiers
1684: if (getCombo(COMBO_BREAKTYPE).getText()
1685: .equalsIgnoreCase(
1686: Messages.StyleEditor_theme_uniques))
1687: classifier = new UniqueIntervalFunction();
1688: else if (getCombo(COMBO_BREAKTYPE)
1689: .getText()
1690: .equalsIgnoreCase(
1691: Messages.StyleEditor_theme_equalInterval))
1692: classifier = new EqualIntervalFunction();
1693: else if (getCombo(COMBO_BREAKTYPE)
1694: .getText()
1695: .equalsIgnoreCase(
1696: Messages.StyleEditor_theme_quantile))
1697: classifier = new QuantileFunction();
1698: else if (getCombo(COMBO_BREAKTYPE)
1699: .getText()
1700: .equalsIgnoreCase(
1701: Messages.StyleEditor_theme_standardDeviation))
1702: classifier = new StandardDeviationFunction();
1703: else if (getCombo(COMBO_BREAKTYPE).getText()
1704: .equalsIgnoreCase(
1705: Messages.StyleEditor_theme_custom))
1706: classifier = customBreak;
1707: else {
1708: return;
1709: }
1710: ProgressListener cancelProgress = ((StyleEditorDialog) getContainer())
1711: .getProgressListener();
1712: classifier.setProgressListener(cancelProgress);
1713: numClasses = new Integer(getCombo(COMBO_CLASSES)
1714: .getText()).intValue();
1715: if (getCombo(COMBO_ELSE).getSelectionIndex() == 0) {
1716: classifier.setNumberOfClasses(numClasses);
1717: } else {
1718: classifier.setNumberOfClasses(numClasses - 1);
1719: }
1720: classifier.setCollection(collection);
1721: classifier.setExpression(expr); //set the expression last, since it causes the calculation
1722: }
1723:
1724: //generate the style
1725: Color[] colors = getBrewer().getPalette(paletteName)
1726: .getColors(numClasses);
1727: if (reverseColours) {
1728: for (int i = 0; i < colors.length / 2; i++) {
1729: Color tempColor = colors[i];
1730: int j = colors.length - i - 1;
1731: colors[i] = colors[j];
1732: colors[j] = tempColor;
1733: }
1734: }
1735:
1736: if (sg == null) {
1737: sg = new StyleGenerator(colors, classifier,
1738: semanticTypeIdentifier);
1739: } else {
1740: sg.setColors(colors);
1741: sg.setCollection(collection);
1742: sg.setClassifier(classifier);
1743: sg.setExpression(expr);
1744: sg.setNumClasses(numClasses);//?
1745: sg.setTypeId(semanticTypeIdentifier);
1746: }
1747: if (getCombo(COMBO_ELSE).getSelectionIndex() == 0) {
1748: sg.setElseMode(StyleGenerator.ELSEMODE_IGNORE);
1749: } else if (getCombo(COMBO_ELSE).getSelectionIndex() == 1) {
1750: sg
1751: .setElseMode(StyleGenerator.ELSEMODE_INCLUDEASMIN);
1752: } else if (getCombo(COMBO_ELSE).getSelectionIndex() == 2) {
1753: sg
1754: .setElseMode(StyleGenerator.ELSEMODE_INCLUDEASMAX);
1755: }
1756: int opacIndex = getCombo(COMBO_OPACITY)
1757: .getSelectionIndex();
1758: double opac;
1759: if (opacIndex > -1) {
1760: opac = opacity[opacIndex];
1761: } else {
1762: opac = 1;
1763: }
1764: sg.setOpacity(opac);
1765: //TODO: justify outline colour (read existing stroke)
1766: sg.setDefaultStroke(sb.createStroke(Color.BLACK, 1,
1767: opac));
1768:
1769: FeatureTypeStyle newFTS;
1770: try {
1771: newFTS = sg
1772: .createFeatureTypeStyle(getSelectedLayer()
1773: .getSchema().getDefaultGeometry());
1774: } catch (IllegalFilterException e) {
1775: newFTS = null;
1776: SLDPlugin.log(
1777: "sg.createFeatureTypeStyle() failed", e); //$NON-NLS-1$
1778: } catch (NullPointerException e) {
1779: newFTS = null;
1780: SLDPlugin.log(
1781: "sg.createFeatureTypeStyle() failed", e); //$NON-NLS-1$
1782: }
1783: if (newFTS == null) {
1784: ErrorManager.get().displayError(
1785: Messages.StyleEditor_error,
1786: Messages.StyleEditor_theme_failure);
1787: // MessageDialog
1788: // .openError(
1789: // PlatformUI.getWorkbench()
1790: // .getActiveWorkbenchWindow()
1791: // .getShell(),
1792: // Messages.StyleEditor_error,
1793: // Messages.StyleEditor_theme_failure);
1794: return;
1795: } else {
1796: //set the FeatureTypeName to the current layer name
1797: newFTS.setFeatureTypeName(getSelectedLayer()
1798: .getSchema().getTypeName());
1799: //get the style
1800: Style style = getStyle();
1801: //ensure the style has an SLD
1802: if (style == null)
1803: throw new RuntimeException("Style is null"); //$NON-NLS-1$
1804: StyledLayerDescriptor sld = SLDs
1805: .styledLayerDescriptor(style);
1806: if (sld == null) {
1807: SLDContent
1808: .createDefaultStyledLayerDescriptor(style);
1809: sld = SLDs.styledLayerDescriptor(style);
1810: if (sld == null)
1811: throw new RuntimeException("SLD is null"); //$NON-NLS-1$
1812: }
1813: //insert/replace the FTS
1814: try {
1815: addThemedFTStoStyle(style, newFTS);
1816: } catch (Exception e) {
1817: String msg = "addThemedFTStoStyle() failed"; //$NON-NLS-1$
1818: SLDPlugin.log(msg, e);
1819: ErrorManager.get().displayException(e, msg,
1820: SLDPlugin.ID);
1821: return;
1822: }
1823:
1824: //update the suitability icons
1825: updateSuitabilities(suitability);
1826:
1827: treeViewer.setInput(newFTS);
1828: }
1829: }
1830: };
1831: try {
1832: BusyIndicator.showWhile(Display.getCurrent(), genDefault);
1833: } catch (Exception e) {
1834: String msg = "Theme Generation Failed"; //$NON-NLS-1$
1835: SLDPlugin.log(msg, e);
1836: ErrorManager.get().displayException(e, msg, SLDPlugin.ID);
1837: }
1838:
1839: //turn cancel off; go back to "close"
1840: ((StyleEditorDialog) getContainer()).setCancelMode(false);
1841:
1842: //resize the palette selection table
1843: displayBottomComposite();
1844: TableUtils.resizeColumns(treeViewer.getTree(), tableSettings,
1845: TableUtils.MODE_JUMP);
1846: //TODO: only the first time
1847:
1848: treeViewer.getControl().setVisible(true);
1849: }
1850:
1851: /**
1852: * Iterates through the style blackboard style and returns the ColorBrewer FeatureTypeStyle.
1853: *
1854: * @return
1855: */
1856: private FeatureTypeStyle getFTS() {
1857: Style style = getStyle();
1858: FeatureTypeStyle[] fts = style.getFeatureTypeStyles();
1859: for (int i = 0; i < fts.length; i++) {
1860: if (SLDs.isSemanticTypeMatch(fts[i], "colorbrewer:.*")) { //$NON-NLS-1$
1861: return fts[i];
1862: }
1863: }
1864: return null;
1865: }
1866:
1867: /**
1868: * Given a Style object and a FeatureTypeStyle, this method scans the SemanticTypeIdentifiers of
1869: * each FTS inside the style. If a ColorBrewer themed identifier is found, the new FTS will
1870: * replace it.
1871: *
1872: * @param style future parent of the FTS
1873: * @param fts FTS to insert/replace with
1874: */
1875: private void addThemedFTStoStyle(Style style, FeatureTypeStyle fts) {
1876: //determine what symbolizers exist in the fts
1877: Set<Object> symbs = new HashSet<Object>();
1878: Rule[] newRules = fts.getRules();
1879: for (int i = 0; i < newRules.length; i++) {
1880: Symbolizer[] newSymbs = newRules[i].getSymbolizers();
1881: for (int j = 0; j < newSymbs.length; j++) {
1882: symbs.add(newSymbs[j].getClass());
1883: }
1884: }
1885:
1886: FeatureTypeStyle[] FTSs = style.getFeatureTypeStyles();
1887: //search for a match, and replace if found
1888: boolean found = false;
1889: for (int i = 0; i < FTSs.length; i++) {
1890: if (SLDs.isSemanticTypeMatch(FTSs[i], "colorbrewer:.*")) { //$NON-NLS-1$
1891: FTSs[i] = fts;
1892: found = true;
1893: } else {
1894: //purge any conflicting Symbolizers (same class)
1895: //TODO: add conditions under which other Symbolizers might live
1896: Rule[] rule = FTSs[i].getRules();
1897: for (int j = 0; j < rule.length; j++) {
1898: Symbolizer[] symb = rule[j].getSymbolizers();
1899: Symbolizer[] newSymb = symb.clone();
1900: int deletedElements = 0;
1901: for (int k = 0; k < symb.length; k++) {
1902: if (symbs.contains(symb[k].getClass())) { //the Symbolizer class is a match
1903: Object[] temp = removeElement(newSymb, k
1904: - deletedElements);
1905: if (temp.length > 0) {
1906: newSymb = new Symbolizer[temp.length];
1907: for (int l = 0; l < temp.length; l++) {
1908: newSymb[l] = (Symbolizer) temp[l];
1909: }
1910: } else {
1911: newSymb = new Symbolizer[0];
1912: }
1913: deletedElements++;
1914: }
1915: }
1916: if (deletedElements > 0) {
1917: rule[j].setSymbolizers(newSymb);
1918: }
1919: }
1920: }
1921: }
1922: //delete any rules with zero symbolizers
1923: for (int i = 0; i < FTSs.length; i++) {
1924: boolean changed = false;
1925: Rule[] rule = FTSs[i].getRules();
1926: for (int j = 0; j < rule.length; j++) {
1927: if (rule[j].getSymbolizers().length == 0) {
1928: if (rule.length > 1) {
1929: Object[] temp = removeElement(rule, j);
1930: rule = new Rule[temp.length];
1931: for (int k = 0; k < temp.length; k++) {
1932: rule[k] = (Rule) temp[k];
1933: }
1934: } else {
1935: rule = new Rule[0];
1936: }
1937: changed = true;
1938: j--;
1939: }
1940: }
1941: if (changed) {
1942: FTSs[i].setRules(rule);
1943: }
1944: }
1945: //delete any FTSs with zero rules
1946: for (int i = 0; i < FTSs.length; i++) {
1947: if (FTSs[i].getRules().length == 0) {
1948: Object[] temp = removeElement(FTSs, i);
1949: FTSs = new FeatureTypeStyle[temp.length];
1950: for (int j = 0; j < temp.length; j++) {
1951: FTSs[j] = (FeatureTypeStyle) temp[j];
1952: }
1953: }
1954: }
1955: //create a FTS if needed
1956: if (!found) {
1957: //match was not found, so add the FTS
1958: FeatureTypeStyle[] newFTSList = new FeatureTypeStyle[FTSs.length + 1];
1959: newFTSList[0] = fts; //add the new fts to the START of the array
1960: System.arraycopy(FTSs, 0, newFTSList, 1, FTSs.length);
1961: style.setFeatureTypeStyles(newFTSList);
1962: } else {
1963: style.setFeatureTypeStyles(FTSs);
1964: }
1965: }
1966:
1967: private Object[] removeElement(Object[] array, int indexToRemove) {
1968: if (array.length == 1)
1969: return new Object[0];
1970: Object[] newArray = new Object[array.length - 1];
1971: if (indexToRemove > 0) {
1972: System.arraycopy(array, 0, newArray, 0, indexToRemove);
1973: }
1974: if (indexToRemove < array.length - 1) {
1975: System.arraycopy(array, indexToRemove + 1, newArray,
1976: indexToRemove, array.length - indexToRemove - 1);
1977: }
1978: return newArray;
1979: }
1980:
1981: private AttributeType getAttributeType(String attributeTypeName) {
1982: FeatureType featureType = getSelectedLayer().getSchema();
1983: for (int i = 0; i < featureType.getAttributeCount(); i++) {
1984: AttributeType attributeType = featureType
1985: .getAttributeType(i);
1986: if (attributeType.getName().equals(attributeTypeName))
1987: return attributeType;
1988: }
1989: return null;
1990: }
1991:
1992: private void createBrewer() {
1993: brewer = PlatformGIS.getColorBrewer();
1994: }
1995:
1996: @Override
1997: public void styleChanged(GTEvent arg) {
1998: }
1999:
2000: public void gotFocus() {
2001: };
2002:
2003: private void displayBottomComposite() {
2004: Object layout = paletteTable.getControl().getLayoutData();
2005: if (layout instanceof GridData) {
2006: GridData gd = (GridData) layout;
2007: gd.grabExcessVerticalSpace = false;
2008: gd.heightHint = 70; //50 ~= 4 lines, 70 ~= 5 lines
2009: }
2010: getLabel(LABEL_SEPARATOR_BOTTOM).setVisible(true);
2011: getLayoutData(COMPOSITE_MIDDLE).grabExcessVerticalSpace = false;
2012: getComposite(COMPOSITE_BOTTOM).setVisible(true);
2013: getLayoutData(COMPOSITE_BOTTOM).grabExcessVerticalSpace = true;
2014: getLayoutData(COMPOSITE_BOTTOM_LEFT).grabExcessVerticalSpace = true;
2015:
2016: getComposite(COMPOSITE_MIDDLE).layout();
2017: getComposite(COMPOSITE_BOTTOM).layout();
2018: getComposite(COMPOSITE_PARENT).layout();
2019: }
2020:
2021: private void updateSuitabilities(int[] suitability) {
2022: for (Iterator i = viewerQuality.keySet().iterator(); i
2023: .hasNext();) {
2024: Object key = i.next();
2025: int icon = ((Integer) viewerQuality.get(key)).intValue();
2026: int quality = suitability[((Integer) key).intValue()];
2027: String viewer = Messages.StyleEditor_theme_suitability_visiblefor
2028: + " " //$NON-NLS-1$
2029: + controlNames.get(icon) + " "; //$NON-NLS-1$
2030: Label label = getLabel(icon);
2031: if (quality == PaletteSuitability.QUALITY_GOOD) {
2032: //getLabel(icon).setImage(getImageWithOverlay(icon, Images.getDescriptor(ImageConstants.GOOD_OVERLAY)));
2033: label.setImage(getImageWithOverlay(icon, null));
2034: label.setToolTipText(viewer
2035: + Messages.StyleEditor_theme_suitability_good);
2036: } else if (quality == PaletteSuitability.QUALITY_DOUBTFUL) {
2037: getLabel(icon)
2038: .setImage(
2039: getImageWithOverlay(
2040: icon,
2041: Images
2042: .getDescriptor(ImageConstants.DOUBTFUL_OVERLAY)));
2043: label
2044: .setToolTipText(viewer
2045: + Messages.StyleEditor_theme_suitability_doubtful);
2046: } else if (quality == PaletteSuitability.QUALITY_BAD) {
2047: getLabel(icon)
2048: .setImage(
2049: getImageWithOverlay(
2050: icon,
2051: Images
2052: .getDescriptor(ImageConstants.BAD_OVERLAY)));
2053: label.setToolTipText(viewer
2054: + Messages.StyleEditor_theme_suitability_bad);
2055: } else { //UNKNOWN
2056: getLabel(icon)
2057: .setImage(
2058: getImageWithOverlay(
2059: icon,
2060: Images
2061: .getDescriptor(ImageConstants.UNKNOWN_OVERLAY)));
2062: label
2063: .setToolTipText(viewer
2064: + Messages.StyleEditor_theme_suitability_unknown);
2065: }
2066: }
2067: }
2068:
2069: private Image getImageWithOverlay(int iconLabelID,
2070: ImageDescriptor overlay) {
2071: //get the base image
2072: ImageDescriptor descriptor = null;
2073: Image base = null;
2074: if (iconLabelID == LABEL_ICON_COLORBLIND)
2075: descriptor = Images
2076: .getDescriptor(ImageConstants.COLORBLIND_ICON);
2077: else if (iconLabelID == LABEL_ICON_CRT)
2078: descriptor = Images.getDescriptor(ImageConstants.CRT_ICON);
2079: else if (iconLabelID == LABEL_ICON_LCD)
2080: descriptor = Images
2081: .getDescriptor(ImageConstants.LAPTOP_ICON);
2082: else if (iconLabelID == LABEL_ICON_PHOTOCOPY)
2083: descriptor = Images
2084: .getDescriptor(ImageConstants.PHOTOCOPY_ICON);
2085: else if (iconLabelID == LABEL_ICON_PRINT)
2086: descriptor = Images
2087: .getDescriptor(ImageConstants.PRINTER_ICON);
2088: else if (iconLabelID == LABEL_ICON_PROJECTOR)
2089: descriptor = Images
2090: .getDescriptor(ImageConstants.PROJECTOR_ICON);
2091: if (descriptor != null)
2092: base = descriptor.createImage();
2093: if (overlay == null)
2094: return base;
2095: //apply the overlay
2096: DecoratorOverlayIcon ovrIcon = new DecoratorOverlayIcon(
2097: base,
2098: new ImageDescriptor[] { null, null, overlay, null, null });
2099: return ovrIcon.createImage();
2100: }
2101:
2102: public boolean performApply() {
2103: return true;
2104: }
2105:
2106: public void refresh() {
2107: //TODO: add refresh method
2108: }
2109: }
|