diff options
author | NAME <USER@epfl.ch> | 2008-06-10 08:29:37 +0000 |
---|---|---|
committer | NAME <USER@epfl.ch> | 2008-06-10 08:29:37 +0000 |
commit | 113c79559555dd408ea76da5f462025536cbd7d6 (patch) | |
tree | 92fb9b3b45fed60d0b128d4aa963d25819d8b525 /src/swing | |
parent | f918ad1886bcdd678a5ea5a1a67948ddedf1ab9a (diff) | |
download | scala-113c79559555dd408ea76da5f462025536cbd7d6.tar.gz scala-113c79559555dd408ea76da5f462025536cbd7d6.tar.bz2 scala-113c79559555dd408ea76da5f462025536cbd7d6.zip |
Fixed Table, wrapped more of button
Diffstat (limited to 'src/swing')
-rw-r--r-- | src/swing/scala/swing/AbstractButton.scala | 81 | ||||
-rw-r--r-- | src/swing/scala/swing/Button.scala | 37 | ||||
-rw-r--r-- | src/swing/scala/swing/Component.scala | 7 | ||||
-rw-r--r-- | src/swing/scala/swing/Frame.scala | 2 | ||||
-rw-r--r-- | src/swing/scala/swing/Key.scala | 195 | ||||
-rw-r--r-- | src/swing/scala/swing/PushButton.scala | 18 | ||||
-rw-r--r-- | src/swing/scala/swing/Table.scala | 37 | ||||
-rw-r--r-- | src/swing/scala/swing/UIElement.scala | 7 | ||||
-rw-r--r-- | src/swing/script/Keys.scala | 44 |
9 files changed, 366 insertions, 62 deletions
diff --git a/src/swing/scala/swing/AbstractButton.scala b/src/swing/scala/swing/AbstractButton.scala new file mode 100644 index 0000000000..d21f71aaaa --- /dev/null +++ b/src/swing/scala/swing/AbstractButton.scala @@ -0,0 +1,81 @@ +package scala.swing + +import java.awt.Dimension +import javax.swing.{AbstractButton => JAbstractButton, Icon} +import event._ + +/** + * Base class of all button-like widgets, such as push buttons, + * check boxes, and radio buttons. + * + * @see javax.swing.AbstractButton + */ +abstract class AbstractButton extends Component with Action.Trigger with Publisher { + override lazy val peer: JAbstractButton = new JAbstractButton {} + + def text: String = peer.getText + def text_=(s: String) = peer.setText(s) + + def icon: Icon = peer.getIcon + def icon_=(i: Icon) = peer.setIcon(i) + def pressedIcon: Icon = peer.getPressedIcon + def pressedIcon_=(i: Icon) = peer.setPressedIcon(i) + def selectedIcon: Icon = peer.getSelectedIcon + def selectedIcon_=(i: Icon) = peer.setSelectedIcon(i) + def disabledIcon: Icon = peer.getDisabledIcon + def disabledIcon_=(i: Icon) = peer.setDisabledIcon(i) + def disabledSelectedIcon: Icon = peer.getDisabledSelectedIcon + def disabledSelectedIcon_=(i: Icon) = peer.setDisabledSelectedIcon(i) + def rolloverIcon: Icon = peer.getRolloverIcon + def rolloverIcon_=(b: Icon) = peer.setRolloverIcon(b) + def rolloverSelectedIcon: Icon = peer.getRolloverSelectedIcon + def rolloverSelectedIcon_=(b: Icon) = peer.setRolloverSelectedIcon(b) + + private var _action: Action = Action.NoAction + def action: Action = _action + def action_=(a: Action) { _action = a; peer.setAction(a.peer) } + + //1.6: def hideActionText: Boolean = peer.getHideActionText + //def hideActionText_=(b: Boolean) = peer.setHideActionText(b) + + peer.addActionListener(new java.awt.event.ActionListener { + def actionPerformed(e: java.awt.event.ActionEvent) { + publish(ButtonClicked(AbstractButton.this)) + } + }) + + def selected: Boolean = peer.isSelected + def selected_=(b: Boolean) = peer.setSelected(b) + + def contentAreaFilled: Boolean = peer.isContentAreaFilled() + def contentAreaFilled_=(b: Boolean) { peer.setContentAreaFilled(true) } + + def borderPainted: Boolean = peer.isBorderPainted + def borderPainted_=(b: Boolean) { peer.setBorderPainted(b) } + def focusPainted: Boolean = peer.isFocusPainted + def focusPainted_=(b: Boolean) { peer.setFocusPainted(b) } + + def rolloverEnabled: Boolean = peer.isRolloverEnabled + def rolloverEnabled_=(b: Boolean) = peer.setRolloverEnabled(b) + + def verticalTextPosition: Alignment.Value = Alignment(peer.getVerticalTextPosition) + def verticalTextPosition_=(a: Alignment.Value) { peer.setVerticalTextPosition(a.id) } + def verticalAlignment: Alignment.Value = Alignment(peer.getVerticalAlignment) + def verticalAlignment_=(a: Alignment.Value) { peer.setVerticalAlignment(a.id) } + + def horizontalTextPosition: Alignment.Value = Alignment(peer.getHorizontalTextPosition) + def horizontalTextPosition_=(a: Alignment.Value) { peer.setHorizontalTextPosition(a.id) } + def horizontalAlignment: Alignment.Value = Alignment(peer.getHorizontalAlignment) + def horizontalAlignment_=(a: Alignment.Value) { peer.setHorizontalAlignment(a.id) } + + def iconTextGap: Int = peer.getIconTextGap + def iconTextGap_=(x: Int) { peer.setIconTextGap(x) } + + def mnemonic: Key.Value = Key(peer.getMnemonic) + def mnemonic_=(k: Key.Value) { peer.setMnemonic(k.id) } + def displayedMnemonicIndex: Int = peer.getDisplayedMnemonicIndex + def displayedMnemonicIndex_=(n: Int) { peer.setDisplayedMnemonicIndex(n) } + + def multiClickThreshold: Long = peer.getMultiClickThreshhold + def multiClickThreshold_=(n: Long) { peer.setMultiClickThreshhold(n) } +} diff --git a/src/swing/scala/swing/Button.scala b/src/swing/scala/swing/Button.scala index fcf164d9b0..c28773a9c4 100644 --- a/src/swing/scala/swing/Button.scala +++ b/src/swing/scala/swing/Button.scala @@ -1,35 +1,18 @@ package scala.swing -import javax.swing.{AbstractButton => JAbstractButton,Icon} +import javax.swing._ import event._ /** - * Base class of all button-like widgets, such as push buttons, - * check boxes, and radio buttons. + * A button that can be pushed, usually to perfrom some action. * - * @see javax.swing.AbstractButton + * @see javax.swing.JButton */ -abstract class AbstractButton extends Component with Action.Trigger with Publisher { - override lazy val peer: JAbstractButton = new JAbstractButton {} - - def text: String = peer.getText - def text_=(s: String) = peer.setText(s) - def icon: Icon = peer.getIcon - def icon_=(i: Icon) = peer.setIcon(i) - - private var _action: Action = Action.NoAction - def action: Action = _action - def action_=(a: Action) { _action = a; peer.setAction(a.peer) } - - //1.6: def hideActionText: Boolean = peer.getHideActionText - //def hideActionText_=(b: Boolean) = peer.setHideActionText(b) - - peer.addActionListener(new java.awt.event.ActionListener { - def actionPerformed(e: java.awt.event.ActionEvent) { - publish(ButtonClicked(AbstractButton.this)) - } - }) - - def selected: Boolean = peer.isSelected - def selected_=(b: Boolean) = peer.setSelected(b) +class Button(text0: String) extends AbstractButton with Publisher { + override lazy val peer: JButton = new JButton(text0) + def this() = this("") + def this(a: Action) = { + this("") + action = a + } } diff --git a/src/swing/scala/swing/Component.scala b/src/swing/scala/swing/Component.scala index 384fc7d882..2039a09d36 100644 --- a/src/swing/scala/swing/Component.scala +++ b/src/swing/scala/swing/Component.scala @@ -26,13 +26,6 @@ abstract class Component extends UIElement with Publisher { override lazy val peer: javax.swing.JComponent = new javax.swing.JComponent{} peer.putClientProperty(Component.ClientKey, this) - def minimumSize = peer.getMinimumSize - def minimumSize_=(x: Dimension) = peer.setMinimumSize(x) - def maximumSize = peer.getMaximumSize - def maximumSize_=(x: Dimension) = peer.setMaximumSize(x) - def preferredSize = peer.getPreferredSize - def preferredSize_=(x: Dimension) = peer.setPreferredSize(x) - /** * Used by certain layout managers, e.g., BoxLayout or OverlayLayout to * align components relative to each other. diff --git a/src/swing/scala/swing/Frame.scala b/src/swing/scala/swing/Frame.scala index afccd28aef..4b790cc905 100644 --- a/src/swing/scala/swing/Frame.scala +++ b/src/swing/scala/swing/Frame.scala @@ -26,6 +26,8 @@ class Frame extends UIElement with RootPanel with Publisher { peer.getRootPane.setDefaultButton(Swing.toNull(b.map(_.peer))) } + def dispose() { peer.dispose() } + def pack(): this.type = { peer.pack(); this } def menuBar: MenuBar = Component.wrapperFor(peer.getJMenuBar) diff --git a/src/swing/scala/swing/Key.scala b/src/swing/scala/swing/Key.scala new file mode 100644 index 0000000000..7a127c1a79 --- /dev/null +++ b/src/swing/scala/swing/Key.scala @@ -0,0 +1,195 @@ +package scala.swing + +object Key extends Enumeration { + import java.awt.event.KeyEvent._ + + val Enter = Value(VK_ENTER) + val BackSpace = Value(VK_BACK_SPACE) + val Tab = Value(VK_TAB) + val Cancel = Value(VK_CANCEL) + val Clear = Value(VK_CLEAR) + val Shift = Value(VK_SHIFT) + val Control = Value(VK_CONTROL) + val Alt = Value(VK_ALT) + val Pause = Value(VK_PAUSE) + val CapsLock = Value(VK_CAPS_LOCK) + val Escape = Value(VK_ESCAPE) + val Space = Value(VK_SPACE) + val PageUp = Value(VK_PAGE_UP) + val PageDown = Value(VK_PAGE_DOWN) + val End = Value(VK_END) + val Home = Value(VK_HOME) + val Left = Value(VK_LEFT) + val Up = Value(VK_UP) + val Right = Value(VK_RIGHT) + val Down = Value(VK_DOWN) + val Comma = Value(VK_COMMA) + val Minus = Value(VK_MINUS) + val Period = Value(VK_PERIOD) + val Slash = Value(VK_SLASH) + val Key0 = Value(VK_0) + val Key1 = Value(VK_1) + val Key2 = Value(VK_2) + val Key3 = Value(VK_3) + val Key4 = Value(VK_4) + val Key5 = Value(VK_5) + val Key6 = Value(VK_6) + val Key7 = Value(VK_7) + val Key8 = Value(VK_8) + val Key9 = Value(VK_9) + val Semicolon = Value(VK_SEMICOLON) + val Equals = Value(VK_EQUALS) + val A = Value(VK_A) + val B = Value(VK_B) + val C = Value(VK_C) + val D = Value(VK_D) + val E = Value(VK_E) + val F = Value(VK_F) + val G = Value(VK_G) + val H = Value(VK_H) + val I = Value(VK_I) + val J = Value(VK_J) + val K = Value(VK_K) + val L = Value(VK_L) + val M = Value(VK_M) + val N = Value(VK_N) + val O = Value(VK_O) + val P = Value(VK_P) + val Q = Value(VK_Q) + val R = Value(VK_R) + val S = Value(VK_S) + val T = Value(VK_T) + val U = Value(VK_U) + val V = Value(VK_V) + val W = Value(VK_W) + val X = Value(VK_X) + val Y = Value(VK_Y) + val Z = Value(VK_Z) + val OpenBracket = Value(VK_OPEN_BRACKET) + val BackSlash = Value(VK_BACK_SLASH) + val CloseBracket = Value(VK_CLOSE_BRACKET) + val Numpad0 = Value(VK_NUMPAD0) + val Numpad1 = Value(VK_NUMPAD1) + val Numpad2 = Value(VK_NUMPAD2) + val Numpad3 = Value(VK_NUMPAD3) + val Numpad4 = Value(VK_NUMPAD4) + val Numpad5 = Value(VK_NUMPAD5) + val Numpad6 = Value(VK_NUMPAD6) + val Numpad7 = Value(VK_NUMPAD7) + val Numpad8 = Value(VK_NUMPAD8) + val Numpad9 = Value(VK_NUMPAD9) + val Multiply = Value(VK_MULTIPLY) + val Add = Value(VK_ADD) + val Separater = Value(VK_SEPARATER) + val Separator = Value(VK_SEPARATOR) + val Subtract = Value(VK_SUBTRACT) + val Decimal = Value(VK_DECIMAL) + val Divide = Value(VK_DIVIDE) + val Delete = Value(VK_DELETE) + val NumLock = Value(VK_NUM_LOCK) + val ScrollLock = Value(VK_SCROLL_LOCK) + val F1 = Value(VK_F1) + val F2 = Value(VK_F2) + val F3 = Value(VK_F3) + val F4 = Value(VK_F4) + val F5 = Value(VK_F5) + val F6 = Value(VK_F6) + val F7 = Value(VK_F7) + val F8 = Value(VK_F8) + val F9 = Value(VK_F9) + val F10 = Value(VK_F10) + val F11 = Value(VK_F11) + val F12 = Value(VK_F12) + val F13 = Value(VK_F13) + val F14 = Value(VK_F14) + val F15 = Value(VK_F15) + val F16 = Value(VK_F16) + val F17 = Value(VK_F17) + val F18 = Value(VK_F18) + val F19 = Value(VK_F19) + val F20 = Value(VK_F20) + val F21 = Value(VK_F21) + val F22 = Value(VK_F22) + val F23 = Value(VK_F23) + val F24 = Value(VK_F24) + val Printscreen = Value(VK_PRINTSCREEN) + val Insert = Value(VK_INSERT) + val Help = Value(VK_HELP) + val Meta = Value(VK_META) + val BackQuote = Value(VK_BACK_QUOTE) + val Quote = Value(VK_QUOTE) + val KpUp = Value(VK_KP_UP) + val KpDown = Value(VK_KP_DOWN) + val KpLeft = Value(VK_KP_LEFT) + val KpRight = Value(VK_KP_RIGHT) + val DeadGrave = Value(VK_DEAD_GRAVE) + val DeadAcute = Value(VK_DEAD_ACUTE) + val DeadCircumflex = Value(VK_DEAD_CIRCUMFLEX) + val DeadTilde = Value(VK_DEAD_TILDE) + val DeadMacron = Value(VK_DEAD_MACRON) + val DeadBreve = Value(VK_DEAD_BREVE) + val DeadAbovedot = Value(VK_DEAD_ABOVEDOT) + val DeadDiaeresis = Value(VK_DEAD_DIAERESIS) + val DeadAbovering = Value(VK_DEAD_ABOVERING) + val DeadDoubleacute = Value(VK_DEAD_DOUBLEACUTE) + val DeadCaron = Value(VK_DEAD_CARON) + val DeadCedilla = Value(VK_DEAD_CEDILLA) + val DeadOgonek = Value(VK_DEAD_OGONEK) + val DeadIota = Value(VK_DEAD_IOTA) + val DeadVoicedSound = Value(VK_DEAD_VOICED_SOUND) + val DeadSemivoicedSound = Value(VK_DEAD_SEMIVOICED_SOUND) + val Ampersand = Value(VK_AMPERSAND) + val Asterisk = Value(VK_ASTERISK) + val Quotedbl = Value(VK_QUOTEDBL) + val Less = Value(VK_LESS) + val Greater = Value(VK_GREATER) + val Braceleft = Value(VK_BRACELEFT) + val Braceright = Value(VK_BRACERIGHT) + val At = Value(VK_AT) + val Colon = Value(VK_COLON) + val Circumflex = Value(VK_CIRCUMFLEX) + val Dollar = Value(VK_DOLLAR) + val EuroSign = Value(VK_EURO_SIGN) + val ExclamationMark = Value(VK_EXCLAMATION_MARK) + val InvertedExclamationMark = Value(VK_INVERTED_EXCLAMATION_MARK) + val LeftParenthesis = Value(VK_LEFT_PARENTHESIS) + val NumberSign = Value(VK_NUMBER_SIGN) + val Plus = Value(VK_PLUS) + val RightParenthesis = Value(VK_RIGHT_PARENTHESIS) + val Underscore = Value(VK_UNDERSCORE) + val Windows = Value(VK_WINDOWS) + val ContextMenu = Value(VK_CONTEXT_MENU) + val Final = Value(VK_FINAL) + val Convert = Value(VK_CONVERT) + val Nonconvert = Value(VK_NONCONVERT) + val Accept = Value(VK_ACCEPT) + val Modechange = Value(VK_MODECHANGE) + val Kana = Value(VK_KANA) + val Kanji = Value(VK_KANJI) + val Alphanumeric = Value(VK_ALPHANUMERIC) + val Katakana = Value(VK_KATAKANA) + val Hiragana = Value(VK_HIRAGANA) + val FullWidth = Value(VK_FULL_WIDTH) + val HalfWidth = Value(VK_HALF_WIDTH) + val RomanCharacters = Value(VK_ROMAN_CHARACTERS) + val AllCandidates = Value(VK_ALL_CANDIDATES) + val PreviousCandidate = Value(VK_PREVIOUS_CANDIDATE) + val CodeInput = Value(VK_CODE_INPUT) + val JapaneseKatakana = Value(VK_JAPANESE_KATAKANA) + val JapaneseHiragana = Value(VK_JAPANESE_HIRAGANA) + val JapaneseRoman = Value(VK_JAPANESE_ROMAN) + val KanaLock = Value(VK_KANA_LOCK) + val InputMethodOnOff = Value(VK_INPUT_METHOD_ON_OFF) + val Cut = Value(VK_CUT) + val Copy = Value(VK_COPY) + val Paste = Value(VK_PASTE) + val Undo = Value(VK_UNDO) + val Again = Value(VK_AGAIN) + val Find = Value(VK_FIND) + val Props = Value(VK_PROPS) + val Stop = Value(VK_STOP) + val Compose = Value(VK_COMPOSE) + val AltGraph = Value(VK_ALT_GRAPH) + val Begin = Value(VK_BEGIN) + val Undefined = Value(VK_UNDEFINED) +} diff --git a/src/swing/scala/swing/PushButton.scala b/src/swing/scala/swing/PushButton.scala deleted file mode 100644 index c28773a9c4..0000000000 --- a/src/swing/scala/swing/PushButton.scala +++ /dev/null @@ -1,18 +0,0 @@ -package scala.swing - -import javax.swing._ -import event._ - -/** - * A button that can be pushed, usually to perfrom some action. - * - * @see javax.swing.JButton - */ -class Button(text0: String) extends AbstractButton with Publisher { - override lazy val peer: JButton = new JButton(text0) - def this() = this("") - def this(a: Action) = { - this("") - action = a - } -} diff --git a/src/swing/scala/swing/Table.scala b/src/swing/scala/swing/Table.scala index e2080a5e39..e4c957e2a5 100644 --- a/src/swing/scala/swing/Table.scala +++ b/src/swing/scala/swing/Table.scala @@ -34,9 +34,10 @@ class Table extends Component with Scrollable with Publisher { override lazy val peer: JTable = new JTable { override def getCellRenderer(r: Int, c: Int) = new TableCellRenderer { def getTableCellRendererComponent(table: JTable, value: AnyRef, isSelected: Boolean, hasFocus: Boolean, row: Int, column: Int) = - renderer(isSelected, hasFocus, row, column).peer + Table.this.renderer(isSelected, hasFocus, row, column).peer } override def getCellEditor(r: Int, c: Int) = editor(r, c) + override def getValueAt(r: Int, c: Int) = Table.this.apply(r,c) } import Table._ @@ -56,7 +57,11 @@ class Table extends Component with Scrollable with Publisher { } def this(rows: Int, columns: Int) = { this() - peer.setModel(new DefaultTableModel(rows, columns)) + model = new DefaultTableModel(rows, columns) { + override def setValueAt(value: Any, row: Int, col: Int) { + super.setValueAt(value, row, col) + } + } } protected def scrollablePeer = peer @@ -67,7 +72,10 @@ class Table extends Component with Scrollable with Publisher { def rowCount = peer.getRowCount def model = peer.getModel() - def model_=(x: TableModel) = peer.setModel(x) + def model_=(x: TableModel) = { + peer.setModel(x) + model.addTableModelListener(modelListener) + } def autoResizeMode: AutoResizeMode.Value = AutoResizeMode(peer.getAutoResizeMode) def autoResizeMode_=(x: Table.AutoResizeMode.Value) = peer.setAutoResizeMode(x.id) @@ -163,21 +171,29 @@ class Table extends Component with Scrollable with Publisher { new Component { override lazy val peer = { val v = Table.this.peer.getValueAt(row, column) - Table.this.peer.getDefaultRenderer(v.getClass).getTableCellRendererComponent(Table.this.peer, + if (v != null) + Table.this.peer.getDefaultRenderer(v.getClass).getTableCellRendererComponent(Table.this.peer, + v, isSelected, hasFocus, row, column).asInstanceOf[JComponent] + else Table.this.peer.getDefaultRenderer(classOf[Object]).getTableCellRendererComponent(Table.this.peer, v, isSelected, hasFocus, row, column).asInstanceOf[JComponent] } } // TODO: a public API for setting editors - protected def editor(row: Int, column: Int) = - Table.this.peer.getDefaultEditor(Table.this.peer.getValueAt(row, column).getClass) + protected def editor(row: Int, column: Int) = { + val v = Table.this.peer.getValueAt(row, column) + if (v != null) + Table.this.peer.getDefaultEditor(v.getClass) + else + Table.this.peer.getDefaultEditor(classOf[Object]) + } - def apply(row: Int, column: Int) = peer.getValueAt(row, column) - def update(row: Int, column: Int, value: Any) = peer.setValueAt(value, row, column) + def apply(row: Int, column: Int) = model.getValueAt(row, column) + def update(row: Int, column: Int, value: Any) = model.setValueAt(value, row, column) def markUpdated(row: Int, column: Int) = update(row, column, apply(row, column)) - model.addTableModelListener(new TableModelListener { + protected val modelListener = new TableModelListener { def tableChanged(e: TableModelEvent) = publish( e.getType match { case TableModelEvent.UPDATE => @@ -193,5 +209,6 @@ class Table extends Component with Scrollable with Publisher { TableRowsRemoved(Table.this, e.getFirstRow to e.getLastRow) } ) - }) + } + model.addTableModelListener(modelListener) } diff --git a/src/swing/scala/swing/UIElement.scala b/src/swing/scala/swing/UIElement.scala index 6f5b91a0b6..7101f0ae27 100644 --- a/src/swing/scala/swing/UIElement.scala +++ b/src/swing/scala/swing/UIElement.scala @@ -12,6 +12,13 @@ trait UIElement { def background: Color = peer.getBackground def background_=(c: Color) = peer.setBackground(c) + def minimumSize = peer.getMinimumSize + def minimumSize_=(x: Dimension) = peer.setMinimumSize(x) + def maximumSize = peer.getMaximumSize + def maximumSize_=(x: Dimension) = peer.setMaximumSize(x) + def preferredSize = peer.getPreferredSize + def preferredSize_=(x: Dimension) = peer.setPreferredSize(x) + def font: Font = peer.getFont def font_=(f: Font) = peer.setFont(f) diff --git a/src/swing/script/Keys.scala b/src/swing/script/Keys.scala new file mode 100644 index 0000000000..70d1ae6eed --- /dev/null +++ b/src/swing/script/Keys.scala @@ -0,0 +1,44 @@ +package script + +import java.lang.reflect._ + +object Keys extends Application { + generate() + + def generate() = { + val fields = classOf[java.awt.event.KeyEvent].getFields + val prefix = "VK_" + val lines = for (f <- fields; if ((f.getModifiers & Modifier.STATIC) != 0) && f.getName.startsWith(prefix)) yield { + val id = f.getInt(null) + val name = javaConstantName2Scala(prefix, f.getName, "Key") + "val " + name + " = Value(" + f.getName + ")" + } + val source = new StringBuilder + source.append("object Key extends Enumeration {\n") + source.append(" import java.awt.event.KeyEvent._\n\n") + lines.foreach(l => source.append(" " + l + "\n")) + source.append("}") + println(source) + } + + def javaConstantName2Scala(prefix: String, name: String, prefixForNumber: String): String = { + var lower = false + var last = ' ' + val builder = new StringBuilder + val trimmed = name.substring(prefix.length) + val n = if (trimmed(0).isDigit) prefixForNumber + trimmed else trimmed + for (val c <- n) { + if (c == '_') { + lower = false + } + else if (lower == true) { + builder.append(c.toLowerCase) + } + else { + lower = true + builder.append(c) + } + } + builder.toString + } +} |