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 +#include + +#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 */ + +