commit 74f35cea774703bd9cd68e386facf365faba71d6
Author: Simon Howard <fraggle@soulsphere.org>
AuthorDate: Sun Jun 5 00:04:59 2016 -0400
Commit: Simon Howard <fraggle@soulsphere.org>
CommitDate: Sun Jun 5 00:04:59 2016 -0400
textscreen: Add widget for conditionally hiding.
A common pattern when using libtextscreen is to want to show or hide
particular UI components depending on the values of particular
variables. It is also common to want to only add things to the UI if
a particular boolean condition is true. Add a new conditional widget
to cover the first case, and a convenience TXT_If() function for the
latter.
---
textscreen/Makefile.am | 1 +
textscreen/textscreen.h | 1 +
textscreen/txt_conditional.c | 166 +++++++++++++++++++++++++++++++++++++++++++
textscreen/txt_conditional.h | 63 ++++++++++++++++
4 files changed, 231 insertions(+)
diff --git a/textscreen/Makefile.am b/textscreen/Makefile.am
index ab828038..fa479bb3 100644
--- a/textscreen/Makefile.am
+++ b/textscreen/Makefile.am
@@ -13,6 +13,7 @@ EXTRA_DIST=Doxyfile
libtextscreen_a_SOURCES = \
textscreen.h \
+ txt_conditional.c txt_conditional.h \
txt_checkbox.c txt_checkbox.h \
txt_desktop.c txt_desktop.h \
txt_dropdown.c txt_dropdown.h \
diff --git a/textscreen/textscreen.h b/textscreen/textscreen.h
index 34c8bf96..d88b58ca 100644
--- a/textscreen/textscreen.h
+++ b/textscreen/textscreen.h
@@ -20,6 +20,7 @@
#include "txt_button.h"
#include "txt_checkbox.h"
+#include "txt_conditional.h"
#include "txt_desktop.h"
#include "txt_dropdown.h"
#include "txt_fileselect.h"
diff --git a/textscreen/txt_conditional.c b/textscreen/txt_conditional.c
new file mode 100644
index 00000000..a341080d
--- /dev/null
+++ b/textscreen/txt_conditional.c
@@ -0,0 +1,166 @@
+//
+// Copyright(C) 2016 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// 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.
+//
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "txt_conditional.h"
+#include "txt_strut.h"
+
+struct txt_conditional_s
+{
+ txt_widget_t widget;
+ int *var;
+ int expected_value;
+ txt_widget_t *child;
+};
+
+static int ConditionTrue(txt_conditional_t *conditional)
+{
+ return *conditional->var == conditional->expected_value;
+}
+
+static int TXT_CondSelectable(TXT_UNCAST_ARG(conditional))
+{
+ TXT_CAST_ARG(txt_conditional_t, conditional);
+ return ConditionTrue(conditional)
+ && TXT_SelectableWidget(conditional->child);
+}
+
+static void TXT_CondSizeCalc(TXT_UNCAST_ARG(conditional))
+{
+ TXT_CAST_ARG(txt_conditional_t, conditional);
+
+ if (!ConditionTrue(conditional))
+ {
+ conditional->widget.w = 0;
+ conditional->widget.h = 0;
+ }
+ else
+ {
+ TXT_CalcWidgetSize(conditional->child);
+ conditional->widget.w = conditional->child->w;
+ conditional->widget.h = conditional->child->h;
+ }
+}
+
+static void TXT_CondLayout(TXT_UNCAST_ARG(conditional))
+{
+ TXT_CAST_ARG(txt_conditional_t, conditional);
+
+ if (ConditionTrue(conditional))
+ {
+ conditional->child->x = conditional->widget.x;
+ conditional->child->y = conditional->widget.y;
+ TXT_LayoutWidget(conditional->child);
+ }
+}
+
+static void TXT_CondDrawer(TXT_UNCAST_ARG(conditional))
+{
+ TXT_CAST_ARG(txt_conditional_t, conditional);
+
+ if (ConditionTrue(conditional))
+ {
+ TXT_DrawWidget(conditional->child);
+ }
+}
+
+static void TXT_CondDestructor(TXT_UNCAST_ARG(conditional))
+{
+ TXT_CAST_ARG(txt_conditional_t, conditional);
+ TXT_DestroyWidget(conditional->child);
+}
+
+static void TXT_CondFocused(TXT_UNCAST_ARG(conditional), int focused)
+{
+ TXT_CAST_ARG(txt_conditional_t, conditional);
+
+ if (ConditionTrue(conditional))
+ {
+ TXT_SetWidgetFocus(conditional->child, focused);
+ }
+}
+
+static int TXT_CondKeyPress(TXT_UNCAST_ARG(conditional), int key)
+{
+ TXT_CAST_ARG(txt_conditional_t, conditional);
+
+ if (ConditionTrue(conditional))
+ {
+ return TXT_WidgetKeyPress(conditional->child, key);
+ }
+
+ return 0;
+}
+
+static void TXT_CondMousePress(TXT_UNCAST_ARG(conditional),
+ int x, int y, int b)
+{
+ TXT_CAST_ARG(txt_conditional_t, conditional);
+
+ if (ConditionTrue(conditional))
+ {
+ TXT_WidgetMousePress(conditional->child, x, y, b);
+ }
+}
+
+txt_widget_class_t txt_conditional_class =
+{
+ TXT_CondSelectable,
+ TXT_CondSizeCalc,
+ TXT_CondDrawer,
+ TXT_CondKeyPress,
+ TXT_CondDestructor,
+ TXT_CondMousePress,
+ TXT_CondLayout,
+ TXT_CondFocused,
+};
+
+txt_conditional_t *TXT_NewConditional(int *var, int expected_value,
+ TXT_UNCAST_ARG(child))
+{
+ TXT_CAST_ARG(txt_widget_t, child);
+ txt_conditional_t *conditional;
+
+ conditional = malloc(sizeof(txt_conditional_t));
+
+ TXT_InitWidget(conditional, &txt_conditional_class);
+ conditional->var = var;
+ conditional->expected_value = expected_value;
+ conditional->child = child;
+
+ return conditional;
+}
+
+// "Static" conditional that returns an empty strut if the given static
+// value is false. Kind of like a conditional but we only evaluate it at
+// creation time.
+txt_widget_t *TXT_If(int conditional, TXT_UNCAST_ARG(child))
+{
+ TXT_CAST_ARG(txt_widget_t, child);
+
+ if (conditional)
+ {
+ return child;
+ }
+ else
+ {
+ txt_strut_t *nullwidget;
+ TXT_DestroyWidget(child);
+ nullwidget = TXT_NewStrut(0, 0);
+ return &nullwidget->widget;
+ }
+}
+
diff --git a/textscreen/txt_conditional.h b/textscreen/txt_conditional.h
new file mode 100644
index 00000000..e30d81ba
--- /dev/null
+++ b/textscreen/txt_conditional.h
@@ -0,0 +1,63 @@
+//
+// Copyright(C) 2016 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// 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.
+//
+
+#ifndef TXT_CONDITIONAL_H
+#define TXT_CONDITIONAL_H
+
+/**
+ * @file txt_conditional.h
+ *
+ * Conditional widget.
+ */
+
+/**
+ * Conditional widget.
+ *
+ * A conditional widget contains another widget, and conditionally
+ * shows or hides it based on the value of a variable.
+ */
+
+typedef struct txt_conditional_s txt_conditional_t;
+
+#include "txt_widget.h"
+
+/**
+ * Create a new conditional widget.
+ *
+ * @param var The variable to check.
+ * @param expected_value If the variable has this value, the widget is shown.
+ * @param child The inner widget to show or hide.
+ * @return Pointer to the new conditional widget.
+ */
+
+txt_conditional_t *TXT_NewConditional(int *var, int expected_value,
+ TXT_UNCAST_ARG(child));
+
+/**
+ * Return the given child widget if the given boolean condition is true.
+ *
+ * If the condition is not true, the child widget is destroyed and a dummy
+ * "null" widget is returned that shows nothing.
+ *
+ * @param condition Boolean condition - true or false value.
+ * @param child Widget to conditionally return.
+ * @return Either child (if condition is true) or a null
+ * widget.
+ */
+
+txt_widget_t *TXT_If(int condition, TXT_UNCAST_ARG(child));
+
+#endif /* #ifndef TXT_CONDITIONAL_H */
+
+