ref: 74f35cea774703bd9cd68e386facf365faba71d6
parent: 15425bce9c68ba6a00777c0bc6640850b4c002a0
author: Simon Howard <fraggle@soulsphere.org>
date: Sat Jun 4 20:04:59 EDT 2016
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.
--- a/textscreen/Makefile.am
+++ b/textscreen/Makefile.am
@@ -13,6 +13,7 @@
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 \
--- 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"
--- /dev/null
+++ b/textscreen/txt_conditional.c
@@ -1,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;
+ }
+}
+
--- /dev/null
+++ b/textscreen/txt_conditional.h
@@ -1,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 */
+
+