/* * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.example.calculator; import griffon.core.artifact.GriffonView; import griffon.inject.MVCMember; import griffon.metadata.ArtifactProviderFor; import griffon.util.CollectionUtils; import net.miginfocom.swing.MigLayout; import org.codehaus.griffon.runtime.swing.artifact.AbstractSwingGriffonView; import org.opendolphin.core.client.ClientDolphin; import org.opendolphin.core.client.ClientPresentationModel; import javax.annotation.Nonnull; import javax.inject.Inject; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import static griffon.util.GriffonClassUtils.getPropertyValue; import static griffon.util.GriffonClassUtils.setPropertyValue; import static org.example.calculator.CalculatorPM.ATTR_ERROR; import static org.example.calculator.CalculatorPM.ATTR_OP1; import static org.example.calculator.CalculatorPM.ATTR_OP2; import static org.example.calculator.CalculatorPM.ATTR_RESULT; import static org.example.calculator.CalculatorPM.PM_CALCULATION; import static org.opendolphin.binding.Binder.bind; @ArtifactProviderFor(GriffonView.class) public class CalculatorView extends AbstractSwingGriffonView { private static final String TEXT = "text"; private CalculatorController controller; private CalculatorModel model; @MVCMember public void setController(@Nonnull CalculatorController controller) { this.controller = controller; } @MVCMember public void setModel(@Nonnull CalculatorModel model) { this.model = model; } @Inject private ClientDolphin clientDolphin; private JPanel calculatorWidget; @Nonnull public JComponent getCalculatorWidget() { return calculatorWidget; } @Override public void initUI() { calculatorWidget = new JPanel(new MigLayout("fill", "[label, pref!][grow, 100!][pref!]")); calculatorWidget.add(new JLabel("Operand 1:"), "left"); JTextField op1Field = new JTextField(); op1Field.setName(ATTR_OP1); op1Field.setHorizontalAlignment(SwingConstants.RIGHT); op1Field.getDocument().addDocumentListener(new TextFieldBinder(ATTR_OP1, op1Field)); calculatorWidget.add(op1Field, "grow"); Action action = toolkitActionFor(controller, "sum"); JButton button = new JButton(action); button.setText("+"); calculatorWidget.add(button, "right, wrap"); calculatorWidget.add(new JLabel("Operand 2:"), "left"); JTextField op2Field = new JTextField(); op2Field.setName(ATTR_OP2); op2Field.setHorizontalAlignment(SwingConstants.RIGHT); op2Field.getDocument().addDocumentListener(new TextFieldBinder(ATTR_OP2, op2Field)); calculatorWidget.add(op2Field, "grow"); action = toolkitActionFor(controller, "sub"); button = new JButton(action); button.setText("-"); calculatorWidget.add(button, "right, wrap"); calculatorWidget.add(new JLabel("Result"), "left"); final JTextField resultField = new JTextField(); resultField.setName(ATTR_RESULT); resultField.setEditable(false); resultField.setHorizontalAlignment(SwingConstants.RIGHT); model.addPropertyChangeListener(ATTR_RESULT, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { resultField.setText(String.valueOf(evt.getNewValue())); } }); calculatorWidget.add(resultField, "grow"); action = toolkitActionFor(controller, "mul"); button = new JButton(action); button.setText("*"); calculatorWidget.add(button, "right, wrap"); calculatorWidget.add(new JLabel(), "left"); calculatorWidget.add(new JLabel(), "left"); action = toolkitActionFor(controller, "div"); button = new JButton(action); button.setText("/"); calculatorWidget.add(button, "right, wrap"); bindPresentationModel(); } private void bindPresentationModel() { ClientPresentationModel pm = clientDolphin.presentationModel(PM_CALCULATION, CollectionUtils.<String, Object>map() .e(ATTR_OP1, 0L) .e(ATTR_OP2, 0L) .e(ATTR_RESULT, 0L) .e(ATTR_ERROR, "")); // from PM attributes to model bind(ATTR_OP1).of(pm).to(ATTR_OP1).of(model); bind(ATTR_OP2).of(pm).to(ATTR_OP2).of(model); bind(ATTR_RESULT).of(pm).to(ATTR_RESULT).of(model); // from model to PM attributes bind(ATTR_OP1).of(model).to(ATTR_OP1).of(pm); bind(ATTR_OP2).of(model).to(ATTR_OP2).of(pm); } private class TextFieldBinder implements DocumentListener { private final String propertyName; private final JTextField widget; private TextFieldBinder(String propertyName, JTextField widget) { this.propertyName = propertyName; this.widget = widget; model.addPropertyChangeListener(propertyName, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { Object newValue = evt.getNewValue(); String val = String.valueOf(newValue); if (newValue != null && !val.equals(widget.getText())) { widget.setText(val); } } }); } @Override public void insertUpdate(DocumentEvent e) { compareAndSet(); } @Override public void removeUpdate(DocumentEvent e) { compareAndSet(); } @Override public void changedUpdate(DocumentEvent e) { compareAndSet(); } private void compareAndSet() { Object oldValue = getPropertyValue(model, propertyName); String newValue = widget.getText(); if (newValue != null && !newValue.equals(oldValue)) { setPropertyValue(model, propertyName, newValue); } } } }