1 /* 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package sun.lwawt; 28 29 import java.awt.Component; 30 import java.awt.Dimension; 31 import java.awt.Point; 32 import java.awt.TextArea; 33 import java.awt.event.TextEvent; 34 import java.awt.peer.TextAreaPeer; 35 36 import javax.swing.JScrollBar; 37 import javax.swing.JScrollPane; 38 import javax.swing.JTextArea; 39 import javax.swing.ScrollPaneConstants; 40 import javax.swing.text.Document; 41 import javax.swing.text.JTextComponent; 42 43 final class LWTextAreaPeer 44 extends LWTextComponentPeer<TextArea, LWTextAreaPeer.ScrollableJTextArea> 45 implements TextAreaPeer { 46 47 private static final int DEFAULT_COLUMNS = 60; 48 private static final int DEFAULT_ROWS = 10; 49 50 LWTextAreaPeer(final TextArea target, 51 final PlatformComponent platformComponent) { 52 super(target, platformComponent); 53 } 54 55 @Override 56 protected ScrollableJTextArea createDelegate() { 57 return new ScrollableJTextArea(); 58 } 59 60 @Override 61 public void initialize() { 62 super.initialize(); 63 final int visibility = getTarget().getScrollbarVisibility(); 64 synchronized (getDelegateLock()) { 65 setScrollBarVisibility(visibility); 66 } 67 } 68 69 @Override 70 JTextComponent getTextComponent() { 71 return getDelegate().getView(); 72 } 73 74 @Override 75 protected Component getDelegateFocusOwner() { 76 return getTextComponent(); 77 } 78 79 @Override 80 public Dimension getMinimumSize() { 81 return getMinimumSize(DEFAULT_ROWS, DEFAULT_COLUMNS); 82 } 83 84 @Override 85 public Dimension getMinimumSize(final int rows, final int columns) { 86 return getPreferredSize(rows, columns); 87 } 88 89 @Override 90 public Dimension getPreferredSize(final int rows, final int columns) { 91 final Dimension size = super.getPreferredSize(rows, columns); 92 synchronized (getDelegateLock()) { 93 final JScrollBar vbar = getDelegate().getVerticalScrollBar(); 94 final JScrollBar hbar = getDelegate().getHorizontalScrollBar(); 95 final int scrollbarW = vbar != null ? vbar.getWidth() : 0; 96 final int scrollbarH = hbar != null ? hbar.getHeight() : 0; 97 return new Dimension(size.width + scrollbarW, 98 size.height + scrollbarH); 99 } 100 } 101 102 @Override 103 public void insert(final String text, final int pos) { 104 final ScrollableJTextArea pane = getDelegate(); 105 synchronized (getDelegateLock()) { 106 final JTextArea area = pane.getView(); 107 final boolean doScroll = pos >= area.getDocument().getLength() 108 && area.getDocument().getLength() != 0; 109 area.insert(text, pos); 110 revalidate(); 111 if (doScroll) { 112 final JScrollBar vbar = pane.getVerticalScrollBar(); 113 if (vbar != null) { 114 vbar.setValue(vbar.getMaximum() - vbar.getVisibleAmount()); 115 } 116 } 117 } 118 repaintPeer(); 119 } 120 121 @Override 122 public void setText(final String l) { 123 // Please note that we do not want to post an event 124 // if TextArea.setText() replaces an empty text by an empty text, 125 // that is, if component's text remains unchanged. 126 if (!l.isEmpty() || getTextComponent().getDocument().getLength() != 0) { 127 super.setText(l); 128 } 129 } 130 131 @Override 132 public void replaceRange(final String text, final int start, 133 final int end) { 134 synchronized (getDelegateLock()) { 135 // JTextArea.replaceRange() posts two different events. 136 // Since we make no differences between text events, 137 // the document listener has to be disabled while 138 // JTextArea.replaceRange() is called. 139 final Document document = getTextComponent().getDocument(); 140 document.removeDocumentListener(this); 141 getDelegate().getView().replaceRange(text, start, end); 142 revalidate(); 143 postEvent(new TextEvent(getTarget(), TextEvent.TEXT_VALUE_CHANGED)); 144 document.addDocumentListener(this); 145 } 146 repaintPeer(); 147 } 148 149 private void setScrollBarVisibility(final int visibility) { 150 final ScrollableJTextArea pane = getDelegate(); 151 final JTextArea view = pane.getView(); 152 view.setLineWrap(false); 153 154 switch (visibility) { 155 case TextArea.SCROLLBARS_NONE: 156 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 157 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); 158 view.setLineWrap(true); 159 break; 160 case TextArea.SCROLLBARS_VERTICAL_ONLY: 161 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 162 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 163 view.setLineWrap(true); 164 break; 165 case TextArea.SCROLLBARS_HORIZONTAL_ONLY: 166 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); 167 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 168 break; 169 default: 170 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 171 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 172 break; 173 } 174 } 175 176 @SuppressWarnings("serial") 177 final class ScrollableJTextArea extends JScrollPane { 178 179 ScrollableJTextArea() { 180 super(); 181 getViewport().setView(new JTextAreaDelegate()); 182 } 183 184 public JTextArea getView() { 185 return (JTextArea) getViewport().getView(); 186 } 187 188 @Override 189 public void setEnabled(final boolean enabled) { 190 getViewport().getView().setEnabled(enabled); 191 super.setEnabled(enabled); 192 } 193 194 @SuppressWarnings("serial") 195 private final class JTextAreaDelegate extends JTextArea { 196 197 // Empty non private constructor was added because access to this 198 // class shouldn't be emulated by a synthetic accessor method. 199 JTextAreaDelegate() { 200 super(); 201 } 202 203 @Override 204 public boolean hasFocus() { 205 return getTarget().hasFocus(); 206 } 207 208 @Override 209 public Point getLocationOnScreen() { 210 return LWTextAreaPeer.this.getLocationOnScreen(); 211 } 212 } 213 } 214 }