r2751 - in trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor: . gis
Author: tchemit Date: 2013-11-24 09:43:43 +0100 (Sun, 24 Nov 2013) New Revision: 2751 Url: http://nuiton.org/projects/jaxx/repository/revisions/2751 Log: fixes #2929: Introduce some coordinate editors Added: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/ trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinate.java trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.css trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jaxx trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorHandler.java trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorModel.java trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinate.java trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.css trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jaxx trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorHandler.java trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorModel.java Added: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinate.java =================================================================== --- trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinate.java (rev 0) +++ trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinate.java 2013-11-24 08:43:43 UTC (rev 2751) @@ -0,0 +1,270 @@ +package jaxx.runtime.swing.editor.gis; + +import org.jdesktop.beans.AbstractSerializableBean; + +/** + * Geo coordinate in degree decimal, minute format. + * <p/> + * Created on 10/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 2.6 + */ +public class DmdCoordinate extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + + public static final String PROPERTY_SIGN = "sign"; + + public static final String PROPERTY_DEGREE = "degree"; + + public static final String PROPERTY_MINUTE = "minute"; + + public static final String PROPERTY_DECIMAL = "decimal"; + + protected boolean sign; + + protected Integer degree; + + protected Integer minute; + + protected Integer decimal; + + public static DmdCoordinate empty() { + DmdCoordinate r = new DmdCoordinate(); + return r; + } + + /** + * Methode statique de fabrique de position a partir d'une valeur du format + * decimal. + * <p/> + * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on + * reinitialise les composants de la position a <code>null</code> et la + * methode {@link #isNull()} vaudra alors {@code true}. + * + * @param decimal la valeur au format decimal + * @return une nouvelle instance de position convertie + */ + public static DmdCoordinate valueOf(Float decimal) { + DmdCoordinate r = new DmdCoordinate(); + r.fromDecimal(decimal); + return r; + } + + /** + * Methode statique de fabrique de position a partir d'une valeur du format + * degre décimale minute. + * + * @param d la valeur des degres + * @param m la valeur des minutes + * @param dc la valeur des décimales de minutes + * @return une nouvelle instance de position convertie + */ + public static DmdCoordinate valueOf(boolean sign, int d, int m, int dc) { + DmdCoordinate r = new DmdCoordinate(); + r.setSign(sign); + r.setDegree(d); + r.setMinute(m); + r.setDecimal(dc); + return r; + } + + public boolean isSign() { + return sign; + } + + public Integer getDegree() { + return degree; + } + + public Integer getMinute() { + return minute; + } + + public Integer getDecimal() { + return decimal; + } + + public void setSign(boolean sign) { + Object oldValue = isSign(); + this.sign = sign; + firePropertyChange(PROPERTY_SIGN, oldValue, sign); + } + + public void setDegree(Integer degree) { + Object oldValue = getDegree(); + this.degree = degree; + firePropertyChange(PROPERTY_DEGREE, oldValue, degree); + } + + public void setMinute(Integer minute) { + Object oldValue = getMinute(); + this.minute = minute; + firePropertyChange(PROPERTY_MINUTE, oldValue, minute); + } + + public void setDecimal(Integer decimal) { + Object oldValue = getDecimal(); + this.decimal = decimal; + firePropertyChange(PROPERTY_DECIMAL, oldValue, decimal); + } + + /** + * @return {@code true} si aucune composante n'est renseignée, + * {@code false} autrement. + */ + public boolean isNull() { + return degree == null && minute == null && decimal == null; + } + + public boolean isDegreeNull() { + return degree == null || degree == 0; + } + + public boolean isMinuteNull() { + return minute == null || minute == 0; + } + + public boolean isDecimalNull() { + return decimal == null || decimal == 0; + } + + /** + * Mets a jour les composants de la position a partir d'une valeur decimal. + * <p/> + * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on + * reinitialise les composants de la position a <code>null</code> et la + * methode {@link #isNull()} vaudra alors {@code true}. + * + * @param decimalValue la valeur decimale a convertir (qui peut etre nulle). + */ + public void fromDecimal(Float decimalValue) { + Integer d = null; + Integer m = null; + Integer dc = null; + boolean si = false; + if (decimalValue != null) { + si = decimalValue < 0; + + float absDecimal = Math.abs(decimalValue); + + d = (int) (Math.round(absDecimal + 0.5) - 1); + int rest = Math.round(100 * 60.0f * (absDecimal - d)); + if (rest > 0) { + m = rest / 100; + dc = (rest - m * 100); + + // clean not used values + if (m == 0) { + m = null; + } + if (dc == 0) { + dc = null; + } + } + if (d == 0) { + d = null; + } + } + + degree = d; + minute = m; + decimal = dc; + sign = si; + } + + public Float toDecimal() { + if (isNull()) { + return null; + } + Integer d = getNotNullDegree(); + Integer m = getNotNullMinute(); + Integer dc = getNotNullDecimal(); + Float result = Float.valueOf(d); + result += (m + (dc / 100f)) / 60.0f; + if (sign) { + result *= -1; + } + return result; + } + + public Integer getSignedDegree() { + Integer result = null; + if (!isDegreeNull()) { + result = degree; + if (isSign()) { + result *= -1; + } + } + return result; + } + + public int getNotNullDegree() { + return isDegreeNull() ? 0 : degree; + } + + public int getNotNullMinute() { + return isMinuteNull() ? 0 : minute; + } + + public int getNotNullDecimal() { + return isDecimalNull() ? 0 : decimal; + } + + public boolean isLatitudeDegreeValid() { + boolean result = isDegreeValid(false); + return result; + } + + public boolean isLongitudeDegreeValid() { + boolean result = isDegreeValid(true); + return result; + } + + public boolean isMinuteValid() { + boolean result = true; + if (!isMinuteNull()) { + if (minute == 60) { + + // can not have decimal + result = isDecimalNull(); + } else { + result = 0 <= minute && minute < 60; + } + } + return result; + } + + public boolean isDecimalValid() { + boolean result = isDecimalNull() || (0 <= decimal && decimal < 100); + return result; + } + + @Override + public String toString() { + return "DmdCoordinateComponent{" + + "sign=" + sign + + ", degree=" + degree + + ", minute=" + minute + + ", decimal=" + decimal + + '}'; + } + + protected boolean isDegreeValid(boolean longitude) { + boolean result = true; + if (!isDegreeNull()) { + int bound = longitude ? 180 : 90; + if (bound == degree) { + + // can not have minute nor decimal + result = isMinuteNull() && isDecimalNull(); + } else { + result = 0 <= degree && degree < bound; + } + } + return result; + } + +} Property changes on: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinate.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.css =================================================================== --- trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.css (rev 0) +++ trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.css 2013-11-24 08:43:43 UTC (rev 2751) @@ -0,0 +1,17 @@ +#toolbarLeft { + floatable:false; + borderPainted:false; + visible:{isShowReset()}; +} + +#resetButton { + actionIcon:"combobox-reset"; + toolTipText: {getShowResetTip()}; + focusable:false; + focusPainted:false; + enabled:{isEnabled()}; +} + +#editor { + enabled:{isEnabled()}; +} \ No newline at end of file Property changes on: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.css ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jaxx =================================================================== --- trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jaxx (rev 0) +++ trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditor.jaxx 2013-11-24 08:43:43 UTC (rev 2751) @@ -0,0 +1,38 @@ +<JPanel id='editorPanel' layout='{new BorderLayout()}' + onFocusGained='editor.requestFocus()'> + <import> + java.io.Serializable + java.awt.BorderLayout + javax.swing.JFormattedTextField + </import> + + <!-- show reset property --> + <Boolean id='showReset' javaBean='false'/> + + <!-- show reset tip --> + <String id='showResetTip' javaBean=''/> + + <!-- model --> + <DmdCoordinateEditorModel id='model'/> + + <!-- handler --> + <DmdCoordinateEditorHandler id='handler' constructorParams='this'/> + + <script><![CDATA[ +public void init() { handler.init(); } +public void setBean(Serializable bean) { model.setBean(bean); } +public void setPropertySign(String property ) { model.setPropertySign(property); } +public void setPropertyDegree(String property ) { model.setPropertyDegree(property); } +public void setPropertyMinute(String property ) { model.setPropertyMinute(property); } +public void setPropertyDecimal(String property ) { model.setPropertyDecimal(property); } +public void setLongitudeEditor(boolean longitudeEditor) { model.setLongitudeEditor(longitudeEditor); } +public void setValue(DmdCoordinate value) { handler.setValue(value, false); } +]]> + </script> + + <JToolBar id='toolbarLeft' constraints='BorderLayout.WEST'> + <JButton id='resetButton' onActionPerformed='handler.resetEditor()'/> + </JToolBar> + <JFormattedTextField id='editor' constraints='BorderLayout.CENTER' + onKeyReleased='handler.onKeyReleased(event)'/> +</JPanel> \ No newline at end of file Added: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorHandler.java =================================================================== --- trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorHandler.java (rev 0) +++ trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorHandler.java 2013-11-24 08:43:43 UTC (rev 2751) @@ -0,0 +1,333 @@ +package jaxx.runtime.swing.editor.gis; + +import com.google.common.base.Preconditions; +import jaxx.runtime.swing.editor.bean.BeanUIUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JFormattedTextField; +import javax.swing.text.DefaultFormatterFactory; +import javax.swing.text.MaskFormatter; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; +import java.text.ParseException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Created on 10/16/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 2.6 + */ +public class DmdCoordinateEditorHandler { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(DmdCoordinateEditorHandler.class); + + protected static final Pattern VALUE_PATTERN = Pattern.compile("(.*)°(.*)'(.*)"); + + private final DmdCoordinateEditor ui; + + protected Method signMutator; + + protected Method degreMutator; + + protected Method minuteMutator; + + protected Method decimalMutator; + + protected DefaultFormatterFactory unsignedFactory; + + protected DefaultFormatterFactory signedFactory; + + protected boolean valueIsAdjusting; + + protected boolean valueModelIsAdjusting; + + public DmdCoordinateEditorHandler(DmdCoordinateEditor ui) { + this.ui = ui; + } + + public void init() { + + final DmdCoordinateEditorModel model = ui.getModel(); + + Preconditions.checkNotNull(model.getBean(), "could not find bean in " + ui); + Preconditions.checkNotNull(model.getPropertySign(), "could not find propertySign in " + ui); + Preconditions.checkNotNull(model.getPropertyDegree(), "could not find propertyDegree in " + ui); + Preconditions.checkNotNull(model.getPropertyMinute(), "could not find propertyMinute in " + ui); + Preconditions.checkNotNull(model.getPropertyDecimal(), "could not find propertyDecimal in " + ui); + + Object bean = model.getBean(); + signMutator = BeanUIUtil.getMutator(bean, model.getPropertySign()); + Preconditions.checkNotNull(signMutator, "could not find mutator for " + model.getPropertySign()); + + degreMutator = BeanUIUtil.getMutator(bean, model.getPropertyDegree()); + Preconditions.checkNotNull(degreMutator, "could not find mutator for " + model.getPropertyDegree()); + + minuteMutator = BeanUIUtil.getMutator(bean, model.getPropertyMinute()); + Preconditions.checkNotNull(minuteMutator, "could not find mutator for " + model.getPropertyMinute()); + + decimalMutator = BeanUIUtil.getMutator(bean, model.getPropertyDecimal()); + Preconditions.checkNotNull(decimalMutator, "could not find mutator for " + model.getPropertyDecimal()); + + MaskFormatter unsignedFormatter; + try { + + String pattern = model.getMaskFormatterPattern(); + unsignedFormatter = new MaskFormatter(pattern); + unsignedFormatter.setValidCharacters(" 01234567890"); + } catch (ParseException e) { + // can't happen here + throw new RuntimeException(e); + } + unsignedFactory = new DefaultFormatterFactory(unsignedFormatter); + + MaskFormatter signedFormatter; + try { + + String pattern = model.getMaskFormatterPattern(); + signedFormatter = new MaskFormatter("-" + pattern); + signedFormatter.setValidCharacters(" 01234567890"); + } catch (ParseException e) { + // can't happen here + throw new RuntimeException(e); + } + signedFactory = new DefaultFormatterFactory(signedFormatter); + + JFormattedTextField editor = ui.getEditor(); + editor.setFormatterFactory(unsignedFactory); + editor.setFocusLostBehavior(JFormattedTextField.COMMIT); + + // When editor changes his value, propagate it to model + editor.addPropertyChangeListener("value", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + String newValue = (String) evt.getNewValue(); + if (log.isDebugEnabled()) { + log.debug("Value has changed: " + newValue); + } + DmdCoordinate value = null; + if (newValue != null) { + + Matcher matcher = VALUE_PATTERN.matcher(newValue); + + if (matcher.matches()) { + + String degresStr = matcher.group(1).replaceAll("\\s", ""); + String minutesStr = matcher.group(2).replaceAll("\\s", ""); + String decimalesStr = matcher.group(3).replaceAll("\\s", ""); + + Integer degre = degresStr.isEmpty() || "-".equals(degresStr) ? 0 : Integer.valueOf(degresStr); + Integer minutes = minutesStr.isEmpty() ? 0 : Integer.valueOf(minutesStr); + Integer decimal = decimalesStr.isEmpty() ? 0 : Integer.valueOf(decimalesStr); + + boolean signed = degre < 0; + value = + DmdCoordinate.valueOf(signed, + Math.abs(degre), + minutes, + decimal); + } + } + model.setValue(value); + } + }); + + // When model sign changed, let's push it back in bean + model.addPropertyChangeListener( + DmdCoordinateEditorModel.PROPERTY_SIGN, + new ModelPropertyChangeListener(model, signMutator)); + + // When model degre changed, let's push it back in bean + model.addPropertyChangeListener( + DmdCoordinateEditorModel.PROPERTY_DEGREE, + new ModelPropertyChangeListener(model, degreMutator)); + + // When model minute changed, let's push it back in bean + model.addPropertyChangeListener( + DmdCoordinateEditorModel.PROPERTY_MINUTE, + new ModelPropertyChangeListener(model, minuteMutator)); + + // When model decimal changed, let's push it back in bean + model.addPropertyChangeListener( + DmdCoordinateEditorModel.PROPERTY_DECIMAL, + new ModelPropertyChangeListener(model, decimalMutator)); + } + + public void setValue(DmdCoordinate value, boolean pushToModel) { + + if (valueModelIsAdjusting) { + // avoid re-entrant code + return; + } + + String signStr = ""; + String degreeStr = ""; + String minuteStr = ""; + String decimalStr = ""; + + if (value != null) { + + boolean sign = value.isSign(); + signStr = sign ? "-" : ""; + + Integer degree = value.getDegree(); + degreeStr = degree == null ? "" : degree.toString(); + + Integer minute = value.getMinute(); + minuteStr = minute == null ? "" : minute.toString(); + + Integer decimal = value.getDecimal(); + decimalStr = decimal == null ? "" : decimal.toString(); + } + + DmdCoordinateEditorModel model = ui.getModel(); + + String stringPattern = model.getStringPattern(); + String valueStr = String.format( + stringPattern, + signStr, + StringUtils.leftPad(degreeStr, model.isLongitudeEditor() ? 3 : 2, ' '), + StringUtils.leftPad(minuteStr, 2, ' '), + StringUtils.leftPad(decimalStr, 2, ' ')); + + valueIsAdjusting = !pushToModel; + + try { + ui.getEditor().setValue(valueStr); + } finally { + valueIsAdjusting = false; + } + } + + public void resetEditor() { + // set null value to model + setValue(null, true); + + // use back unsigned format + ui.getEditor().setFormatterFactory(unsignedFactory); + } + + public void onKeyReleased(KeyEvent e) { + + JFormattedTextField source = (JFormattedTextField) e.getSource(); + + char keyChar = e.getKeyChar(); + int caretPosition = source.getCaretPosition(); + if (log.isDebugEnabled()) { + log.debug("Key pressed: " + keyChar + " (caret position: " + caretPosition + ")"); + } + + String newValue = null; + DefaultFormatterFactory newFactory = null; + if (keyChar == '-') { + + // try to switch unsigned to signed + + if (unsignedFactory == source.getFormatterFactory()) { + + // switch to signed + if (log.isDebugEnabled()) { + log.debug("Switch to signed"); + } + newFactory = signedFactory; + + try { + source.commitEdit(); + } catch (ParseException e1) { + // ignore it + } + + newValue = "-" + source.getValue(); + + } else { + // switch to unsigned + + if (log.isDebugEnabled()) { + log.debug("Switch to unsigned"); + } + newFactory = unsignedFactory; + + try { + source.commitEdit(); + } catch (ParseException e1) { + // ignore it + } + + newValue = ((String) source.getValue()).substring(1); + } + } else { + try { + source.commitEdit(); + } catch (ParseException e1) { + // ignore it + } + if (log.isDebugEnabled()) { + log.debug("Key pressed: newValue " + source.getValue()); + } + } + + if (newFactory != null) { + + // consume event (prevent any side-effects) + e.consume(); + + if (log.isDebugEnabled()) { + log.debug("Key pressed: newValue " + newValue); + } + source.setFormatterFactory(newFactory); + source.setValue(newValue); + + if (unsignedFactory == newFactory) { + + // remove a sign + caretPosition--; + } else { + + // add a sign + caretPosition++; + } + + source.setCaretPosition(caretPosition); + } + } + + private class ModelPropertyChangeListener implements PropertyChangeListener { + + private final DmdCoordinateEditorModel model; + + private final Method mutator; + + private ModelPropertyChangeListener(DmdCoordinateEditorModel model, + Method mutator) { + this.model = model; + this.mutator = mutator; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (!valueIsAdjusting) { + Object newValue = evt.getNewValue(); + + try { + + valueModelIsAdjusting = true; + try { + mutator.invoke(model.getBean(), newValue); + } finally { + valueModelIsAdjusting = false; + } + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + } +} Property changes on: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorModel.java =================================================================== --- trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorModel.java (rev 0) +++ trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorModel.java 2013-11-24 08:43:43 UTC (rev 2751) @@ -0,0 +1,127 @@ +package jaxx.runtime.swing.editor.gis; + +import java.io.Serializable; + +/** + * Created on 10/16/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 2.6 + */ +public class DmdCoordinateEditorModel extends DmdCoordinate { + + public static final String PROPERTY_BEAN = "bean"; + + public static final String PROPERTY_PROPERTY_SIGN = "propertySign"; + + public static final String PROPERTY_PROPERTY_DEGREE = "propertyDegree"; + + public static final String PROPERTY_PROPERTY_MINUTE = "propertyMinute"; + + public static final String PROPERTY_PROPERTY_DECIMAL = "propertyDecimal"; + + public static final String PROPERTY_LONGITUDE_EDITOR = "longitudeEditor"; + + private static final long serialVersionUID = 1L; + + /** Bean where to push data. */ + protected Serializable bean; + + /** Name of the property of the bean to fire the change of the {@link #sign}. */ + protected String propertySign; + + /** Name of the property of the bean to fire the change of the {@link #degree}. */ + protected String propertyDegre; + + /** Name of the property of the bean to fire the change of the {@link #minute}. */ + protected String propertyMinute; + + /** Name of the property of the bean to fire the change of the {@link #decimal}. */ + protected String propertyDecimal; + + /** + * {@code true} if longitude editor, {@code false} for latitude editor. + */ + protected boolean longitudeEditor; + + public Serializable getBean() { + return bean; + } + + public void setBean(Serializable bean) { + Object oldValue = getBean(); + this.bean = bean; + firePropertyChange(PROPERTY_BEAN, oldValue, bean); + } + + public String getPropertySign() { + return propertySign; + } + + public void setPropertySign(String propertySign) { + Object oldValue = getPropertySign(); + this.propertySign = propertySign; + firePropertyChange(PROPERTY_PROPERTY_SIGN, oldValue, propertySign); + } + + public String getPropertyDegree() { + return propertyDegre; + } + + public void setPropertyDegree(String propertyDegree) { + Object oldValue = getPropertyDegree(); + this.propertyDegre = propertyDegree; + firePropertyChange(PROPERTY_PROPERTY_DEGREE, oldValue, propertyDegree); + } + + public String getPropertyMinute() { + return propertyMinute; + } + + public void setPropertyMinute(String propertyMinute) { + Object oldValue = getPropertyMinute(); + this.propertyMinute = propertyMinute; + firePropertyChange(PROPERTY_PROPERTY_MINUTE, oldValue, propertyMinute); + } + + public String getPropertyDecimal() { + return propertyDecimal; + } + + public void setPropertyDecimal(String propertyDecimal) { + Object oldValue = getPropertyDecimal(); + this.propertyDecimal = propertyDecimal; + firePropertyChange(PROPERTY_PROPERTY_DECIMAL, oldValue, propertyDecimal); + } + + public boolean isLongitudeEditor() { + return longitudeEditor; + } + + public void setLongitudeEditor(boolean longitudeEditor) { + Object oldValue = isLongitudeEditor(); + this.longitudeEditor = longitudeEditor; + firePropertyChange(PROPERTY_BEAN, oldValue, longitudeEditor); + } + + public void setValue(DmdCoordinate value) { + setSign(value != null && value.isSign()); + setDegree(value == null ? null : value.getDegree()); + setMinute(value == null ? null : value.getMinute()); + setDecimal(value == null ? null : value.getDecimal()); + } + + public String getMaskFormatterPattern() { + String pattern = "**°**''**"; + if (isLongitudeEditor()) { + // add one more degre + pattern = "*" + pattern; + } + return pattern; + } + + public String getStringPattern() { + String pattern = "%s%s°%s'%s"; + return pattern; + } +} Property changes on: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmdCoordinateEditorModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinate.java =================================================================== --- trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinate.java (rev 0) +++ trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinate.java 2013-11-24 08:43:43 UTC (rev 2751) @@ -0,0 +1,300 @@ +package jaxx.runtime.swing.editor.gis; + +import org.jdesktop.beans.AbstractSerializableBean; + +/** + * Geo coordinate in degree, minute, second format. + * <p/> + * Created on 10/23/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 2.6 + */ +public class DmsCoordinate extends AbstractSerializableBean { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_SIGN = "sign"; + + public static final String PROPERTY_DEGREE = "degree"; + + public static final String PROPERTY_MINUTE = "minute"; + + public static final String PROPERTY_SECOND = "second"; + + protected boolean sign; + + protected Integer degree; + + protected Integer minute; + + protected Integer second; + + public static DmsCoordinate empty() { + DmsCoordinate r = new DmsCoordinate(); + return r; + } + + /** + * Methode statique de fabrique de position a partir d'une valeur du format + * decimal. + * <p/> + * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on + * reinitialise les composants de la position a <code>null</code> et la + * methode {@link #isNull()} vaudra alors {@code true}. + * + * @param decimal la valeur au format decimal + * @return une nouvelle instance de position convertie + */ + public static DmsCoordinate valueOf(Float decimal) { + DmsCoordinate r = new DmsCoordinate(); + r.fromDecimal(decimal); + return r; + } + + /** + * Methode statique de fabrique de position a partir d'une valeur du format + * degre-minute-seconde. + * + * @param d la valeur des degres + * @param m la valeur des minutes + * @param s la valeur des secondes + * @return une nouvelle instance de position convertie + */ + public static DmsCoordinate valueOf(boolean sign, int d, int m, int s) { + DmsCoordinate r = new DmsCoordinate(); + r.setSign(sign); + r.setDegree(d); + r.setMinute(m); + r.setSecond(s); + return r; + } + + public boolean isSign() { + return sign; + } + + public Integer getDegree() { + return degree; + } + + public Integer getMinute() { + return minute; + } + + public Integer getSecond() { + return second; + } + + public void setSign(boolean sign) { + Object oldValue = isSign(); + this.sign = sign; + firePropertyChange(PROPERTY_SIGN, oldValue, sign); + } + + public void setDegree(Integer degree) { + Object oldValue = getDegree(); + this.degree = degree; + firePropertyChange(PROPERTY_DEGREE, oldValue, degree); + } + + public void setMinute(Integer minute) { + Object oldValue = getMinute(); + this.minute = minute; + firePropertyChange(PROPERTY_MINUTE, oldValue, minute); + } + + public void setSecond(Integer second) { + Object oldValue = getSecond(); + this.second = second; + firePropertyChange(PROPERTY_SECOND, oldValue, second); + } + + public boolean isDegreeNull() { + return degree == null || degree == 0; + } + + public boolean isMinuteNull() { + return minute == null || minute == 0; + } + + public boolean isSecondNull() { + return second == null || second == 0; + } + + /** + * @return {@code true} si aucune composante n'est renseignée, + * {@code false} autrement. + */ + public boolean isNull() { + return degree == null && minute == null && second == null; + } + + /** + * Mets a jour les composants de la position a partir d'une valeur decimal. + * <p/> + * Note : Si la valeur (au format decimal) vaut <code>null</code>, alors on + * reinitialise les composants de la position a <code>null</code> et la + * methode {@link #isNull()} vaudra alors {@code true}. + * + * @param decimal la valeur decimale a convertir (qui peut etre nulle). + */ + public void fromDecimal(Float decimal) { + Integer d = null; + Integer m = null; + Integer s = null; + boolean si = false; + if (decimal != null) { + si = decimal < 0; + + decimal = Math.abs(decimal); + int remain = 0; + + d = (int) (Math.round(decimal + 0.5) - 1); + m = 0; + s = 0; + decimal = 60.0f * (decimal - d); + if (decimal > 0) { + m = (int) (Math.round(decimal + 0.5) - 1); + decimal = 60 * (decimal - m); + if (decimal > 0) { + s = (int) (Math.round(decimal + 0.5) - 1); + remain = (int) (10 * (decimal - s)); + } + } + if (remain > 9) { + s++; + } + if (s == 60) { + m++; + s = 0; + } + if (m == 60) { + d++; + m = 0; + } + + // clean not used values + if (m == 0) { + m = null; + } + if (s == 0) { + s = null; + } + } + + if (d != null && d == 0) { + d = null; + } + degree = d; + minute = m; + second = s; + sign = si; + + } + + public Float toDecimal() { + if (isNull()) { + return null; + } + Integer d = getNotNullDegree(); + Integer m = getNotNullMinute(); + + Integer s = getNotNullSecond(); + + Float result = Float.valueOf(d); + + if (m > 0) { + result += (float) m / 60; + if (s == 0) { + result += 0.5f / 3600; + } + } + if (s > 0) { + result += ((float) s + 0.5f) / 3600; + } + + if (sign) { + result *= -1; + } + return result; + } + + public Integer getSignedDegree() { + Integer result = null; + if (!isDegreeNull()) { + result = degree; + if (isSign()) { + result *= -1; + } + } + return result; + } + + public int getNotNullDegree() { + return isDegreeNull() ? 0 : degree; + } + + public int getNotNullMinute() { + return isMinuteNull() ? 0 : minute; + } + + + public int getNotNullSecond() { + return isSecondNull() ? 0 : second; + } + + public boolean isLatitudeDegreeValid() { + boolean result = isDegreeValid(false); + return result; + } + + public boolean isLongitudeDegreeValid() { + boolean result = isDegreeValid(true); + return result; + } + + public boolean isMinuteValid() { + boolean result = true; + if (!isMinuteNull()) { + if (60 == minute) { + + // check minute and second are null + result = isSecondNull(); + } else { + result = 0 <= minute && minute < 60; + } + } + return result; + } + + public boolean isSecondValid() { + boolean result = isSecondNull() || (0 <= second && second < 60); + return result; + } + + @Override + public String toString() { + return "DmsCoordinateComponent{" + + "sign=" + sign + + ", degree=" + degree + + ", minute=" + minute + + ", second=" + second + + '}'; + } + + protected boolean isDegreeValid(boolean longitude) { + boolean result = true; + if (!isDegreeNull()) { + int bound = longitude ? 180 : 90; + if (bound == degree) { + + // check minute and second are null + result = isMinuteNull() && isSecondNull(); + } else { + result = degree < bound; + } + } + return result; + } +} Property changes on: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinate.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.css =================================================================== --- trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.css (rev 0) +++ trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.css 2013-11-24 08:43:43 UTC (rev 2751) @@ -0,0 +1,17 @@ +#toolbarLeft { + floatable:false; + borderPainted:false; + visible:{isShowReset()}; +} + +#resetButton { + actionIcon:"combobox-reset"; + toolTipText: {getShowResetTip()}; + focusable:false; + focusPainted:false; + enabled:{isEnabled()}; +} + +#editor { + enabled:{isEnabled()}; +} \ No newline at end of file Property changes on: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.css ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jaxx =================================================================== --- trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jaxx (rev 0) +++ trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditor.jaxx 2013-11-24 08:43:43 UTC (rev 2751) @@ -0,0 +1,39 @@ +<JPanel id='editorPanel' layout='{new BorderLayout()}' + onFocusGained='editor.requestFocus()'> + <import> + java.io.Serializable + java.awt.BorderLayout + javax.swing.JFormattedTextField + </import> + + <!-- show reset property --> + + <Boolean id='showReset' javaBean='false'/> + + <!-- show reset tip --> + <String id='showResetTip' javaBean=''/> + + <!-- model --> + <DmsCoordinateEditorModel id='model'/> + + <!-- handler --> + <DmsCoordinateEditorHandler id='handler' constructorParams='this'/> + + <script><![CDATA[ +public void init() { handler.init(); } +public void setBean(Serializable bean) { model.setBean(bean); } +public void setPropertySign(String property ) { model.setPropertySign(property); } +public void setPropertyDegree(String property ) { model.setPropertyDegree(property); } +public void setPropertyMinute(String property ) { model.setPropertyMinute(property); } +public void setPropertySecond(String property ) { model.setPropertySecond(property); } +public void setLongitudeEditor(boolean longitudeEditor) { model.setLongitudeEditor(longitudeEditor); } +public void setValue(DmsCoordinate value) { handler.setValue(value, false); } +]]> + </script> + + <JToolBar id='toolbarLeft' constraints='BorderLayout.WEST'> + <JButton id='resetButton' onActionPerformed='handler.resetEditor()'/> + </JToolBar> + <JFormattedTextField id='editor' constraints='BorderLayout.CENTER' + onKeyReleased='handler.onKeyReleased(event)'/> +</JPanel> \ No newline at end of file Added: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorHandler.java =================================================================== --- trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorHandler.java (rev 0) +++ trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorHandler.java 2013-11-24 08:43:43 UTC (rev 2751) @@ -0,0 +1,332 @@ +package jaxx.runtime.swing.editor.gis; + +import com.google.common.base.Preconditions; +import jaxx.runtime.swing.editor.bean.BeanUIUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JFormattedTextField; +import javax.swing.text.DefaultFormatterFactory; +import javax.swing.text.MaskFormatter; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; +import java.text.ParseException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Created on 10/16/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 2.6 + */ +public class DmsCoordinateEditorHandler { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(DmsCoordinateEditorHandler.class); + + protected static final Pattern VALUE_PATTERN = + Pattern.compile("(.*)°(.*)'(.*)''"); + + private final DmsCoordinateEditor ui; + + protected Method signMutator; + + protected Method degreMutator; + + protected Method minuteMutator; + + protected Method secondMutator; + + protected DefaultFormatterFactory unsignedFactory; + + protected DefaultFormatterFactory signedFactory; + + protected boolean valueIsAdjusting; + + protected boolean valueModelIsAdjusting; + + public DmsCoordinateEditorHandler(DmsCoordinateEditor ui) { + this.ui = ui; + } + + public void init() { + + final DmsCoordinateEditorModel model = ui.getModel(); + + Preconditions.checkNotNull(model.getBean(), "could not find bean in " + ui); + Preconditions.checkNotNull(model.getPropertySign(), "could not find propertySign in " + ui); + Preconditions.checkNotNull(model.getPropertyDegree(), "could not find propertyDegree in " + ui); + Preconditions.checkNotNull(model.getPropertyMinute(), "could not find propertyMinute in " + ui); + Preconditions.checkNotNull(model.getPropertySecond(), "could not find propertySecond in " + ui); + + Object bean = model.getBean(); + signMutator = BeanUIUtil.getMutator(bean, model.getPropertySign()); + Preconditions.checkNotNull(signMutator, "could not find mutator for " + model.getPropertySign()); + + degreMutator = BeanUIUtil.getMutator(bean, model.getPropertyDegree()); + Preconditions.checkNotNull(degreMutator, "could not find mutator for " + model.getPropertyDegree()); + + minuteMutator = BeanUIUtil.getMutator(bean, model.getPropertyMinute()); + Preconditions.checkNotNull(minuteMutator, "could not find mutator for " + model.getPropertyMinute()); + + secondMutator = BeanUIUtil.getMutator(bean, model.getPropertySecond()); + Preconditions.checkNotNull(secondMutator, "could not find mutator for " + model.getPropertySecond()); + + MaskFormatter unsignedFormatter; + try { + + String pattern = model.getMaskFormatterPattern(); + unsignedFormatter = new MaskFormatter(pattern); + unsignedFormatter.setValidCharacters(" 01234567890"); + } catch (ParseException e) { + // can't happen here + throw new RuntimeException(e); + } + unsignedFactory = new DefaultFormatterFactory(unsignedFormatter); + + MaskFormatter signedFormatter; + try { + + String pattern = model.getMaskFormatterPattern(); + signedFormatter = new MaskFormatter("-" + pattern); + signedFormatter.setValidCharacters(" 01234567890"); + } catch (ParseException e) { + // can't happen here + throw new RuntimeException(e); + } + signedFactory = new DefaultFormatterFactory(signedFormatter); + + JFormattedTextField editor = ui.getEditor(); + editor.setFormatterFactory(unsignedFactory); + editor.setFocusLostBehavior(JFormattedTextField.COMMIT); + + // When editor changes his value, propagate it to model + editor.addPropertyChangeListener("value", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + String newValue = (String) evt.getNewValue(); + if (log.isDebugEnabled()) { + log.debug("Value has changed: " + newValue); + } + DmsCoordinate value = null; + if (newValue != null) { + + Matcher matcher = VALUE_PATTERN.matcher(newValue); + + if (matcher.matches()) { + + String degresStr = matcher.group(1).replaceAll("\\s", ""); + String minutesStr = matcher.group(2).replaceAll("\\s", ""); + String secondsStr = matcher.group(3).replaceAll("\\s", ""); + + Integer degre = degresStr.isEmpty() || "-".equals(degresStr) ? 0 : Integer.valueOf(degresStr); + Integer minutes = minutesStr.isEmpty() ? 0 : Integer.valueOf(minutesStr); + Integer seconds = secondsStr.isEmpty() ? 0 : Integer.valueOf(secondsStr); + + boolean signed = degre < 0; + value = + DmsCoordinate.valueOf(signed, + Math.abs(degre), + minutes, + seconds); + } + } + model.setValue(value); + } + }); + + // When model sign changed, let's push it back in bean + model.addPropertyChangeListener( + DmsCoordinateEditorModel.PROPERTY_SIGN, + new ModelPropertyChangeListener(model, signMutator)); + + // When model degre changed, let's push it back in bean + model.addPropertyChangeListener( + DmsCoordinateEditorModel.PROPERTY_DEGREE, + new ModelPropertyChangeListener(model, degreMutator)); + + // When model minute changed, let's push it back in bean + model.addPropertyChangeListener( + DmsCoordinateEditorModel.PROPERTY_MINUTE, + new ModelPropertyChangeListener(model, minuteMutator)); + + // When model second changed, let's push it back in bean + model.addPropertyChangeListener( + DmsCoordinateEditorModel.PROPERTY_SECOND, + new ModelPropertyChangeListener(model, secondMutator)); + } + + public void setValue(DmsCoordinate value, boolean pushToModel) { + + if (valueModelIsAdjusting) { + // avoid re-entrant code + return; + } + + String signStr = ""; + String degreeStr = ""; + String minuteStr = ""; + String secondStr = ""; + if (value != null) { + + boolean sign = value.isSign(); + signStr = sign ? "-" : ""; + + Integer degree = value.getDegree(); + degreeStr = degree == null ? "" : degree.toString(); + + Integer minute = value.getMinute(); + minuteStr = minute == null ? "" : minute.toString(); + + Integer second = value.getSecond(); + secondStr = second == null ? "" : second.toString(); + } + + DmsCoordinateEditorModel model = ui.getModel(); + String stringPattern = model.getStringPattern(); + String valueStr = String.format( + stringPattern, + signStr, + StringUtils.leftPad(degreeStr, model.isLongitudeEditor() ? 3 : 2, ' '), + StringUtils.leftPad(minuteStr, 2, ' '), + StringUtils.leftPad(secondStr, 2, ' ')); + + valueIsAdjusting = !pushToModel; + + try { + ui.getEditor().setValue(valueStr); + } finally { + valueIsAdjusting = false; + } + } + + public void resetEditor() { + // set null value to model + setValue(null, true); + + // use back unsigned format + ui.getEditor().setFormatterFactory(unsignedFactory); + } + + public void onKeyReleased(KeyEvent e) { + + JFormattedTextField source = (JFormattedTextField) e.getSource(); + + char keyChar = e.getKeyChar(); + int caretPosition = source.getCaretPosition(); + if (log.isDebugEnabled()) { + log.debug("Key pressed: " + keyChar + " (caret position: " + caretPosition + ")"); + } + + String newValue = null; + DefaultFormatterFactory newFactory = null; + if (keyChar == '-') { + + // try to switch unsigned to signed + + if (unsignedFactory == source.getFormatterFactory()) { + + // switch to signed + if (log.isDebugEnabled()) { + log.debug("Switch to signed"); + } + newFactory = signedFactory; + + try { + source.commitEdit(); + } catch (ParseException e1) { + // ignore it + } + + newValue = "-" + source.getValue(); + + } else { + // switch to unsigned + + if (log.isDebugEnabled()) { + log.debug("Switch to unsigned"); + } + newFactory = unsignedFactory; + + try { + source.commitEdit(); + } catch (ParseException e1) { + // ignore it + } + + newValue = ((String) source.getValue()).substring(1); + } + } else { + try { + source.commitEdit(); + } catch (ParseException e1) { + // ignore it + } + if (log.isDebugEnabled()) { + log.debug("Key pressed: newValue " + source.getValue()); + } + } + + if (newFactory != null) { + + // consume event (prevent any side-effects) + e.consume(); + + + if (log.isDebugEnabled()) { + log.debug("Key pressed: newValue " + newValue); + } + source.setFormatterFactory(newFactory); + source.setValue(newValue); + + if (unsignedFactory == newFactory) { + + // remove a sign + caretPosition--; + } else { + + // add a sign + caretPosition++; + } + + source.setCaretPosition(caretPosition); + } + } + + private class ModelPropertyChangeListener implements PropertyChangeListener { + + private final DmsCoordinateEditorModel model; + + private final Method mutator; + + private ModelPropertyChangeListener(DmsCoordinateEditorModel model, Method mutator) { + this.model = model; + this.mutator = mutator; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (!valueIsAdjusting) { + Object newValue = evt.getNewValue(); + + try { + + valueModelIsAdjusting = true; + try { + mutator.invoke(model.getBean(), newValue); + } finally { + valueModelIsAdjusting = false; + } + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + } +} Property changes on: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorModel.java =================================================================== --- trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorModel.java (rev 0) +++ trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorModel.java 2013-11-24 08:43:43 UTC (rev 2751) @@ -0,0 +1,127 @@ +package jaxx.runtime.swing.editor.gis; + +import java.io.Serializable; + +/** + * Created on 10/16/13. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 2.6 + */ +public class DmsCoordinateEditorModel extends DmsCoordinate { + + public static final String PROPERTY_BEAN = "bean"; + + public static final String PROPERTY_PROPERTY_SIGN = "propertySign"; + + public static final String PROPERTY_PROPERTY_DEGREE = "propertyDegree"; + + public static final String PROPERTY_PROPERTY_MINUTE = "propertyMinute"; + + public static final String PROPERTY_PROPERTY_SECOND = "propertySecond"; + + public static final String PROPERTY_LONGITUDE_EDITOR = "longitudeEditor"; + + private static final long serialVersionUID = 1L; + + /** Bean where to push data. */ + protected Serializable bean; + + /** Name of the property of the bean to fire the change of the {@link #sign}. */ + protected String propertySign; + + /** Name of the property of the bean to fire the change of the {@link #degree}. */ + protected String propertyDegree; + + /** Name of the property of the bean to fire the change of the {@link #minute}. */ + protected String propertyMinute; + + /** Name of the property of the bean to fire the change of the {@link #second}. */ + protected String propertySecond; + + /** + * {@code true} if longitude editor, {@code false} for latitude editor. + */ + protected boolean longitudeEditor; + + public Serializable getBean() { + return bean; + } + + public void setBean(Serializable bean) { + Object oldValue = getBean(); + this.bean = bean; + firePropertyChange(PROPERTY_BEAN, oldValue, bean); + } + + public String getPropertySign() { + return propertySign; + } + + public void setPropertySign(String propertySign) { + Object oldValue = getPropertySign(); + this.propertySign = propertySign; + firePropertyChange(PROPERTY_PROPERTY_SIGN, oldValue, propertySign); + } + + public String getPropertyDegree() { + return propertyDegree; + } + + public void setPropertyDegree(String propertyDegree) { + Object oldValue = getPropertyDegree(); + this.propertyDegree = propertyDegree; + firePropertyChange(PROPERTY_PROPERTY_DEGREE, oldValue, propertyDegree); + } + + public String getPropertyMinute() { + return propertyMinute; + } + + public void setPropertyMinute(String propertyMinute) { + Object oldValue = getPropertyMinute(); + this.propertyMinute = propertyMinute; + firePropertyChange(PROPERTY_PROPERTY_MINUTE, oldValue, propertyMinute); + } + + public String getPropertySecond() { + return propertySecond; + } + + public void setPropertySecond(String propertySecond) { + Object oldValue = getPropertySecond(); + this.propertySecond = propertySecond; + firePropertyChange(PROPERTY_PROPERTY_SECOND, oldValue, propertySecond); + } + + public boolean isLongitudeEditor() { + return longitudeEditor; + } + + public void setLongitudeEditor(boolean longitudeEditor) { + Object oldValue = isLongitudeEditor(); + this.longitudeEditor = longitudeEditor; + firePropertyChange(PROPERTY_BEAN, oldValue, longitudeEditor); + } + + public void setValue(DmsCoordinate value) { + setSign(value != null && value.isSign()); + setDegree(value == null ? null : value.getDegree()); + setMinute(value == null ? null : value.getMinute()); + setSecond(value == null ? null : value.getSecond()); + } + + public String getMaskFormatterPattern() { + String pattern = "**°**''**''''"; + if (isLongitudeEditor()) { + // add one more degre + pattern = "*" + pattern; + } + return pattern; + } + + public String getStringPattern() { + String pattern = "%s%s°%s'%s''"; + return pattern; + } +} Property changes on: trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/gis/DmsCoordinateEditorModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native
participants (1)
-
tchemit@users.nuiton.org