From 7272e49f35db74caa16eead38aa39a80bb9fc641 Mon Sep 17 00:00:00 2001 From: Kevin Lamonte Date: Sat, 14 Mar 2015 17:52:39 -0400 Subject: [PATCH] checkbox working --- README.md | 1 - demos/Demo1.java | 191 ++++++++++++++++++++++++--------------- src/jexer/TCheckbox.java | 149 ++++++++++++++++++++++++++++++ src/jexer/TWidget.java | 61 ++++++++++++- 4 files changed, 328 insertions(+), 74 deletions(-) create mode 100644 src/jexer/TCheckbox.java diff --git a/README.md b/README.md index 2e9ef73..11e09c3 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,6 @@ Many tasks remain before calling this version 1.0: 0.0.1: -- TCheckbox - TDirectoryList - TField - TMessageBox diff --git a/demos/Demo1.java b/demos/Demo1.java index 5d5485a..44333a4 100644 --- a/demos/Demo1.java +++ b/demos/Demo1.java @@ -34,11 +34,55 @@ import jexer.*; import jexer.menu.*; +class DemoCheckboxWindow extends TWindow { + + /** + * Constructor + */ + DemoCheckboxWindow(TApplication parent) { + this(parent, CENTERED | RESIZABLE); + } + + /** + * Constructor + */ + DemoCheckboxWindow(TApplication parent, int flags) { + // Construct a demo window. X and Y don't matter because it + // will be centered on screen. + super(parent, "Radiobuttons and Checkboxes", 0, 0, 60, 15, flags); + + int row = 1; + + // Add some widgets + addLabel("Check box example 1", 1, row); + addCheckbox(35, row++, "Checkbox 1", false); + addLabel("Check box example 2", 1, row); + addCheckbox(35, row++, "Checkbox 2", true); + row += 2; + + /* + auto group = addRadioGroup(1, row, "Group 1"); + group.addRadioButton("Radio option 1"); + group.addRadioButton("Radio option 2"); + group.addRadioButton("Radio option 3"); + + addButton("&Close Window", (width - 14) / 2, height - 4, + { + application.closeWindow(this); + } + + ); + */ + } + +} + + class DemoMsgBoxWindow extends TWindow { /* private void openYNCMessageBox() { - application.messageBox("Yes/No/Cancel MessageBox", - q"EOS + application.messageBox("Yes/No/Cancel MessageBox", + q"EOS This is an example of a Yes/No/Cancel MessageBox. Note that the MessageBox text can span multiple @@ -47,12 +91,12 @@ lines. The default result (if someone hits the top-left close button) is CANCEL. EOS", - TMessageBox.Type.YESNOCANCEL); + TMessageBox.Type.YESNOCANCEL); } private void openYNMessageBox() { - application.messageBox("Yes/No MessageBox", - q"EOS + application.messageBox("Yes/No MessageBox", + q"EOS This is an example of a Yes/No MessageBox. Note that the MessageBox text can span multiple @@ -61,12 +105,12 @@ lines. The default result (if someone hits the top-left close button) is NO. EOS", - TMessageBox.Type.YESNO); + TMessageBox.Type.YESNO); } private void openOKCMessageBox() { - application.messageBox("OK/Cancel MessageBox", - q"EOS + application.messageBox("OK/Cancel MessageBox", + q"EOS This is an example of a OK/Cancel MessageBox. Note that the MessageBox text can span multiple @@ -75,12 +119,12 @@ lines. The default result (if someone hits the top-left close button) is CANCEL. EOS", - TMessageBox.Type.OKCANCEL); + TMessageBox.Type.OKCANCEL); } private void openOKMessageBox() { - application.messageBox("OK MessageBox", - q"EOS + application.messageBox("OK MessageBox", + q"EOS This is an example of a OK MessageBox. This is the default MessageBox. @@ -90,7 +134,7 @@ lines. The default result (if someone hits the top-left close button) is OK. EOS", - TMessageBox.Type.OK); + TMessageBox.Type.OK); } */ @@ -99,55 +143,55 @@ EOS", * Constructor. */ DemoMsgBoxWindow(final TApplication parent) { - this(parent, TWindow.CENTERED | TWindow.RESIZABLE); + this(parent, TWindow.CENTERED | TWindow.RESIZABLE); } /** * Constructor. */ DemoMsgBoxWindow(final TApplication parent, final int flags) { - // Construct a demo window. X and Y don't matter because it - // will be centered on screen. - super(parent, "Message Boxes", 0, 0, 60, 15, flags); + // Construct a demo window. X and Y don't matter because it + // will be centered on screen. + super(parent, "Message Boxes", 0, 0, 60, 15, flags); /* - uint row = 1; - - // Add some widgets - addLabel("Default OK message box", 1, row); - addButton("Open O&K MB", 35, row, &openOKMessageBox); - row += 2; - - addLabel("OK/Cancel message box", 1, row); - addButton("O&pen OKC MB", 35, row, &openOKCMessageBox); - row += 2; - - addLabel("Yes/No message box", 1, row); - addButton("Open &YN MB", 35, row, &openYNMessageBox); - row += 2; - - addLabel("Yes/No/Cancel message box", 1, row); - addButton("Ope&n YNC MB", 35, row, &openYNCMessageBox); - row += 2; - - addLabel("Input box", 1, row); - addButton("Open &input box", 35, row, - { - application.inputBox("Input Box", - q"EOS + uint row = 1; + + // Add some widgets + addLabel("Default OK message box", 1, row); + addButton("Open O&K MB", 35, row, &openOKMessageBox); + row += 2; + + addLabel("OK/Cancel message box", 1, row); + addButton("O&pen OKC MB", 35, row, &openOKCMessageBox); + row += 2; + + addLabel("Yes/No message box", 1, row); + addButton("Open &YN MB", 35, row, &openYNMessageBox); + row += 2; + + addLabel("Yes/No/Cancel message box", 1, row); + addButton("Ope&n YNC MB", 35, row, &openYNCMessageBox); + row += 2; + + addLabel("Input box", 1, row); + addButton("Open &input box", 35, row, + { + application.inputBox("Input Box", + q"EOS This is an example of an InputBox. Note that the InputBox text can span multiple lines. EOS", - "some input text"); - } - ); - - addButton("&Close Window", (width - 14) / 2, height - 4, - { - application.closeWindow(this); - } - ); + "some input text"); + } + ); + + addButton("&Close Window", (width - 14) / 2, height - 4, + { + application.closeWindow(this); + } + ); */ } } @@ -174,11 +218,6 @@ class DemoMainWindow extends TWindow { application.closeWindow(modalWindow); } - /// This is an example of having a button call a function. - private void openCheckboxWindow() { - new DemoCheckboxWindow(application); - } - /// We need to override onClose so that the timer will no longer be /// called after we close the window. TTimers currently are completely /// unaware of the rest of the UI classes. @@ -217,30 +256,40 @@ class DemoMainWindow extends TWindow { } row += 2; - /* addLabel("Open me as modal", 1, row); addButton("W&indow", 35, row, - { - new DemoMainWindow(application, Flag.MODAL); + new TAction() { + public void DO() { + new DemoMainWindow(getApplication(), MODAL); + } } ); row += 2; + /* addLabel("Variable-width text field:", 1, row); addField(35, row++, 15, false, "Field text"); addLabel("Fixed-width text field:", 1, row); addField(35, row, 15, true); row += 2; + */ - if (!isModal) { + if (!isModal()) { addLabel("Radio buttons and checkboxes", 1, row); - addButton("&Checkboxes", 35, row, &openCheckboxWindow); + addButton("&Checkboxes", 35, row, + new TAction() { + public void DO() { + new DemoCheckboxWindow(getApplication(), MODAL); + } + } + ); } row += 2; - if (!isModal) { + /* + if (!isModal()) { addLabel("Editor window", 1, row); addButton("Edito&r", 35, row, { @@ -250,7 +299,7 @@ class DemoMainWindow extends TWindow { } row += 2; - if (!isModal) { + if (!isModal()) { addLabel("Text areas", 1, row); addButton("&Text", 35, row, { @@ -260,7 +309,7 @@ class DemoMainWindow extends TWindow { } row += 2; - if (!isModal) { + if (!isModal()) { addLabel("Tree views", 1, row); addButton("Tree&View", 35, row, { @@ -270,17 +319,15 @@ class DemoMainWindow extends TWindow { } row += 2; - version(Posix) { - if (!isModal) { - addLabel("Terminal", 1, row); - addButton("Termi&nal", 35, row, - { - application.openTerminal(0, 0); - } - ); - } - row += 2; + if (!isModal()) { + addLabel("Terminal", 1, row); + addButton("Termi&nal", 35, row, + { + application.openTerminal(0, 0); + } + ); } + row += 2; TProgressBar bar = addProgressBar(1, row, 22); row++; diff --git a/src/jexer/TCheckbox.java b/src/jexer/TCheckbox.java new file mode 100644 index 0000000..556a11b --- /dev/null +++ b/src/jexer/TCheckbox.java @@ -0,0 +1,149 @@ +/** + * Jexer - Java Text User Interface + * + * License: LGPLv3 or later + * + * This module is licensed under the GNU Lesser General Public License + * Version 3. Please see the file "COPYING" in this directory for more + * information about the GNU Lesser General Public License Version 3. + * + * Copyright (C) 2015 Kevin Lamonte + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * http://www.gnu.org/licenses/, or write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * @author Kevin Lamonte [kevin.lamonte@gmail.com] + * @version 1 + */ +package jexer; + +import jexer.bits.CellAttributes; +import jexer.bits.GraphicsChars; +import jexer.event.TKeypressEvent; +import jexer.event.TMouseEvent; +import static jexer.TKeypress.*; + +/** + * TCheckbox implements an on/off checkbox. + */ +public final class TCheckbox extends TWidget { + + /** + * Checkbox state, true means checked. + */ + private boolean checked = false; + + /** + * Label for this checkbox. + */ + private String label; + + /** + * Public constructor. + * + * @param parent parent widget + * @param x column relative to parent + * @param y row relative to parent + * @param label label to display next to (right of) the checkbox + * @param checked initial check state + */ + public TCheckbox(final TWidget parent, final int x, final int y, + final String label, final boolean checked) { + + // Set parent and window + super(parent); + + setX(x); + setY(y); + setHeight(1); + this.label = label; + setWidth(label.length() + 4); + this.checked = checked; + + setHasCursor(true); + setCursorX(1); + } + + /** + * Returns true if the mouse is currently on the checkbox. + * + * @param mouse mouse event + * @return true if the mouse is currently on the checkbox + */ + private boolean mouseOnCheckbox(final TMouseEvent mouse) { + if ((mouse != null) + && (mouse.getY() == 0) + && (mouse.getX() >= 0) + && (mouse.getX() <= 2) + ) { + return true; + } + return false; + } + + /** + * Draw a checkbox with label. + */ + @Override + public void draw() { + CellAttributes checkboxColor; + + if (getAbsoluteActive()) { + checkboxColor = getTheme().getColor("tcheckbox.active"); + } else { + checkboxColor = getTheme().getColor("tcheckbox.inactive"); + } + + getScreen().putCharXY(0, 0, '[', checkboxColor); + if (checked) { + getScreen().putCharXY(1, 0, GraphicsChars.CHECK, checkboxColor); + } else { + getScreen().putCharXY(1, 0, ' ', checkboxColor); + } + getScreen().putCharXY(2, 0, ']', checkboxColor); + getScreen().putStrXY(4, 0, label, checkboxColor); + } + + /** + * Handle mouse checkbox presses. + * + * @param mouse mouse button down event + */ + @Override + public void onMouseDown(final TMouseEvent mouse) { + if ((mouseOnCheckbox(mouse)) && (mouse.getMouse1())) { + // Switch state + checked = !checked; + } + } + + /** + * Handle keystrokes. + * + * @param keypress keystroke event + */ + @Override + public void onKeypress(final TKeypressEvent keypress) { + if (keypress.equals(kbSpace)) { + checked = !checked; + return; + } + + // Pass to parent for the things we don't care about. + super.onKeypress(keypress); + } + +} diff --git a/src/jexer/TWidget.java b/src/jexer/TWidget.java index 2ca7108..6c03a9c 100644 --- a/src/jexer/TWidget.java +++ b/src/jexer/TWidget.java @@ -312,6 +312,15 @@ public abstract class TWidget implements Comparable { */ private boolean hasCursor = false; + /** + * Set visible cursor flag. + * + * @param hasCursor if true, this widget has a cursor + */ + public final void setHasCursor(final boolean hasCursor) { + this.hasCursor = hasCursor; + } + /** * See if this widget has a visible cursor. * @@ -326,11 +335,47 @@ public abstract class TWidget implements Comparable { */ private int cursorX = 0; + /** + * Get cursor X value. + * + * @return cursor column position in relative coordinates + */ + public final int getCursorX() { + return cursorX; + } + + /** + * Set cursor X value. + * + * @param cursorX column position in relative coordinates + */ + public final void setCursorX(final int cursorX) { + this.cursorX = cursorX; + } + /** * Cursor row position in relative coordinates. */ private int cursorY = 0; + /** + * Get cursor Y value. + * + * @return cursor row position in relative coordinates + */ + public final int getCursorY() { + return cursorY; + } + + /** + * Set cursor Y value. + * + * @param cursorY row position in relative coordinates + */ + public final void setCursorY(final int cursorY) { + this.cursorY = cursorY; + } + /** * Comparison operator sorts on tabOrder for TWidgets and z for TWindows. * @@ -341,7 +386,7 @@ public abstract class TWidget implements Comparable { @Override public final int compareTo(final TWidget that) { if ((this instanceof TWindow) - && (that instanceof TWindow) + && (that instanceof TWindow) ) { return (((TWindow) this).getZ() - ((TWindow) that).getZ()); } @@ -956,5 +1001,19 @@ public abstract class TWidget implements Comparable { return new TButton(this, text, x, y, action); } + /** + * Convenience function to add a checkbox to this container/window. + * + * @param x column relative to parent + * @param y row relative to parent + * @param label label to display next to (right of) the checkbox + * @param checked initial check state + * @return the new checkbox + */ + public final TCheckbox addCheckbox(final int x, final int y, + final String label, final boolean checked) { + + return new TCheckbox(this, x, y, label, checked); + } } -- 2.27.0