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}