View Javadoc
1   package fr.ifremer.quadrige3.ui.swing.component.time;
2   
3   /*-
4    * #%L
5    * Quadrige3 Core :: UI Swing Common
6    * %%
7    * Copyright (C) 2017 - 2019 Ifremer
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Affero General Public License as published by
11   * the Free Software Foundation, either version 3 of the License, or
12   * (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU Affero General Public License
20   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21   * #L%
22   */
23  
24  import fr.ifremer.quadrige3.core.dao.technical.Times;
25  
26  import javax.swing.JFormattedTextField;
27  import javax.swing.event.DocumentEvent;
28  import javax.swing.event.DocumentListener;
29  import javax.swing.text.DefaultFormatterFactory;
30  import javax.swing.text.MaskFormatter;
31  import java.awt.Color;
32  import java.awt.event.FocusEvent;
33  import java.awt.event.FocusListener;
34  import java.text.ParseException;
35  import java.time.LocalTime;
36  import java.time.format.DateTimeParseException;
37  
38  /**
39   * Swing Editor for local time (hours and minutes)
40   * Can handle LocalTime value or number of seconds as Integer
41   *
42   * @author peck7 on 06/02/2019.
43   */
44  public class LocalTimeEditor extends JFormattedTextField implements FocusListener {
45  
46      private static final String MASK = "##:##";
47      private static final char PLACEHOLDER = '_';
48      private static final String EMPTY_MINUTE = "__";
49  
50      private String emptyValue;
51      private boolean adjusting;
52  
53      public LocalTimeEditor() {
54          super();
55  
56          MaskFormatter mask = null;
57          try {
58              mask = new MaskFormatter(MASK);
59              mask.setPlaceholderCharacter(PLACEHOLDER);
60              emptyValue = mask.valueToString(null);
61          } catch (ParseException e) {
62              e.printStackTrace();
63          }
64  
65          setFormatterFactory(new DefaultFormatterFactory(mask));
66  
67          addFocusListener(this);
68  
69          getDocument().addDocumentListener(new DocumentListener() {
70              @Override
71              public void insertUpdate(DocumentEvent e) {
72                  validInput();
73              }
74  
75              @Override
76              public void removeUpdate(DocumentEvent e) {
77                  validInput();
78              }
79  
80              @Override
81              public void changedUpdate(DocumentEvent e) {
82                  validInput();
83              }
84          });
85      }
86  
87      private void validInput() {
88  
89          if (adjusting) return;
90  
91          boolean valid = true;
92          if (!emptyValue.equals(getText())) {
93              try {
94                  Times.stringToSeconds(getText());
95              } catch (DateTimeParseException ex) {
96                  valid = false;
97              }
98          }
99  
100         setForeground(valid ? Color.black : Color.red);
101 
102         if (valid)
103             fireActionPerformed();
104     }
105 
106     @Override
107     protected void fireActionPerformed() {
108         adjusting = true;
109         super.fireActionPerformed();
110         adjusting = false;
111     }
112 
113     @Override
114     public void setText(String t) {
115         if (adjusting) return;
116 
117         adjusting = true;
118         super.setText(t);
119         adjusting = false;
120     }
121 
122     private void addDefaultMinutes() {
123         String text = getText();
124 
125         // Affect 00 as minutes if user doesn't enter it
126         if (text != null && text.endsWith(EMPTY_MINUTE)) {
127             text = text.substring(0, text.length() - EMPTY_MINUTE.length()) + "00";
128             setText(text);
129         }
130     }
131 
132     public LocalTime getLocalTime() {
133         Integer seconds = getTimeInSecond();
134         return seconds != null ? LocalTime.ofSecondOfDay(seconds) : null;
135     }
136 
137     public void setLocalTime(LocalTime localTime) {
138         setTimeInSecond(localTime != null ? localTime.toSecondOfDay() : null);
139     }
140 
141     public Integer getTimeInSecond() {
142 
143         String text = getText();
144         if (emptyValue.equals(text)) {
145             return null;
146         }
147 
148         addDefaultMinutes();
149 
150         Integer result = null;
151         try {
152             result = Times.stringToSeconds(text);
153         } catch (DateTimeParseException ignored) {
154         }
155         return result;
156     }
157 
158     public void setTimeInSecond(Integer seconds) {
159 
160         setText(Times.secondsToString(seconds));
161     }
162 
163     @Override
164     public void focusGained(FocusEvent e) {
165 
166     }
167 
168     @Override
169     public void focusLost(FocusEvent e) {
170         addDefaultMinutes();
171     }
172 
173 }