001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2009 Sun Microsystems, Inc.
015 * Portions Copyright 2015 ForgeRock AS.
016 */
017package org.opends.guitools.controlpanel.ui.components;
018
019import javax.swing.text.AttributeSet;
020import javax.swing.text.BadLocationException;
021import javax.swing.text.DocumentFilter;
022import javax.swing.text.JTextComponent;
023
024/**
025 * Document filter used to update properly a text component displaying a
026 * time.
027 */
028public class TimeDocumentFilter extends DocumentFilter
029{
030  private JTextComponent tf;
031
032  /**
033   * Constructor.
034   * @param tf the text component associated with the document.
035   */
036  public TimeDocumentFilter(JTextComponent tf)
037  {
038    this.tf = tf;
039  }
040
041  /** {@inheritDoc} */
042  public void insertString(DocumentFilter.FilterBypass fb, int offset,
043      String text, AttributeSet attr)
044  throws BadLocationException
045  {
046    int previousLength = fb.getDocument().getLength();
047    fb.insertString(offset, text.replaceAll("[^0-9]", ""), attr);
048    trimPosition(fb, text, offset, previousLength);
049  }
050
051  /** {@inheritDoc} */
052  public void remove(DocumentFilter.FilterBypass fb, int offset,
053      int length)
054  throws BadLocationException
055  {
056    String text = fb.getDocument().getText(offset, length);
057    int index = text.indexOf(":");
058    if (index == -1)
059    {
060      fb.remove(offset, length);
061    }
062    else
063    {
064      // index value is relative to offset
065      if (index > 0)
066      {
067        fb.remove(offset, index);
068      }
069      if (index < length - 1)
070      {
071        fb.remove(offset + index + 1, length - index -1);
072      }
073    }
074    updateCaretPosition(fb);
075  }
076
077  /** {@inheritDoc} */
078  public void replace(DocumentFilter.FilterBypass fb, int offset,
079      int length, String text, AttributeSet attr)
080  throws BadLocationException
081  {
082    int previousLength = fb.getDocument().getLength();
083
084    String t = fb.getDocument().getText(offset, length);
085    int index = t.indexOf(":");
086    fb.replace(offset, length, text.replaceAll("[^0-9]", ""), attr);
087    if (index != -1)
088    {
089      if (fb.getDocument().getLength() >= 2)
090      {
091        fb.insertString(2, ":", attr);
092      }
093      else
094      {
095        fb.insertString(fb.getDocument().getLength(), ":", attr);
096      }
097    }
098
099    trimPosition(fb, text, offset, previousLength);
100  }
101
102  private void trimPosition(DocumentFilter.FilterBypass fb, String newText,
103      int offset, int previousLength)
104  throws BadLocationException
105  {
106    String allText =
107      fb.getDocument().getText(0, fb.getDocument().getLength());
108    int index = allText.indexOf(':');
109    if (index != -1 && newText.length() == 1)
110    {
111      int minuteLength = allText.length() - index - 1;
112      int hourLength = index;
113
114      if (minuteLength > 2 || hourLength > 2)
115      {
116        if (offset < previousLength)
117        {
118          fb.remove(offset + 1, 1);
119        }
120        else
121        {
122          fb.remove(previousLength, 1);
123        }
124      }
125    }
126    updateCaretPosition(fb);
127  }
128
129  private void updateCaretPosition(DocumentFilter.FilterBypass fb)
130  throws BadLocationException
131  {
132    String allText =
133      fb.getDocument().getText(0, fb.getDocument().getLength());
134    int index = allText.indexOf(':');
135    if (index != -1)
136    {
137      int minuteLength = allText.length() - index - 1;
138      int hourLength = index;
139      int caretPosition = tf.getCaretPosition();
140
141      if (minuteLength >= 2 &&
142          caretPosition == allText.length())
143      {
144        tf.setCaretPosition(0);
145      }
146      else if (hourLength == caretPosition)
147      {
148        if (hourLength >= 2)
149        {
150          tf.setCaretPosition(3);
151        }
152        else if (hourLength == 1)
153        {
154          char c = allText.charAt(0);
155          if (c != '0' && c != '1' && c != '2')
156          {
157            tf.setCaretPosition(2);
158          }
159        }
160      }
161      else if (hourLength + 1 == caretPosition)
162      {
163        if (hourLength == 1)
164        {
165          char c = allText.charAt(0);
166          if (c == '0' || c == '1' || c == '2')
167          {
168            tf.setCaretPosition(caretPosition - 1);
169          }
170        }
171        else if (hourLength == 0)
172        {
173          tf.setCaretPosition(caretPosition - 1);
174        }
175      }
176    }
177    if (allText.length() == 1)
178    {
179      tf.setCaretPosition(0);
180    }
181  }
182}