foxygit / doom Log in
commit be3d314a61d68281f02af1248a85e6aa069c4980
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Sat Oct 7 00:59:03 2006 +0000
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Sat Oct 7 00:59:03 2006 +0000

    Add float spin control and use it for the acceleration controller in setup.

    Subversion-branch: /trunk/chocolate-doom
    Subversion-revision: 692
---
 setup/mouse.c             |   4 +-
 textscreen/txt_spinctrl.c | 183 +++++++++++++++++++++++++++++++++++++++-------
 textscreen/txt_spinctrl.h |  10 ++-
 3 files changed, 165 insertions(+), 32 deletions(-)

diff --git a/setup/mouse.c b/setup/mouse.c
index 67e12b23..bd3aa8a5 100644
--- a/setup/mouse.c
+++ b/setup/mouse.c
@@ -30,7 +30,7 @@ int use_mouse = 1;

 int novert;
 int speed;
-int accel;
+float accel;
 int threshold;
 int grabmouse = 1;

@@ -100,7 +100,7 @@ void ConfigMouse(void)
                    TXT_NewLabel("Speed"),
                    TXT_NewSpinControl(&speed, 1, 256),
                    TXT_NewLabel("Acceleration"),
-                   TXT_NewSpinControl(&accel, 1, 5),
+                   TXT_NewFloatSpinControl(&accel, 1.0, 5.0),
                    TXT_NewLabel("Acceleration threshold"),
                    TXT_NewSpinControl(&threshold, 0, 32),
                    NULL);
diff --git a/textscreen/txt_spinctrl.c b/textscreen/txt_spinctrl.c
index 2b00ee59..dcb8a4ee 100644
--- a/textscreen/txt_spinctrl.c
+++ b/textscreen/txt_spinctrl.c
@@ -33,25 +33,76 @@
 #include "txt_main.h"
 #include "txt_window.h"

+// Generate the format string to be used for displaying floats
+
+static void FloatFormatString(float step, char *buf)
+{
+    int precision;
+
+    precision = (int) ceil(-log(step) / log(10));
+
+    if (precision > 0)
+    {
+        sprintf(buf, "%%.%if", precision);
+    }
+    else
+    {
+        strcpy(buf, "%.1f");
+    }
+}
+
 // Number of characters needed to represent a character

 static int IntWidth(int val)
 {
-    char buf[15];
+    char buf[25];

     sprintf(buf, "%i", val);

     return strlen(buf);
 }

+static int FloatWidth(float val, float step)
+{
+    int precision;
+    int result;
+
+    // Calculate the width of the int value
+
+    result = IntWidth((int) val);
+
+    // Add a decimal part if the precision specifies it
+
+    precision = (int) ceil(-log(step) / log(10));
+
+    if (precision > 0)
+    {
+        result += precision + 1;
+    }
+
+    return result;
+}
+
 // Returns the minimum width of the input box

 static int SpinControlWidth(txt_spincontrol_t *spincontrol)
 {
     int minw, maxw;

-    minw = IntWidth(spincontrol->min);
-    maxw = IntWidth(spincontrol->max);
+    switch (spincontrol->type)
+    {
+        case TXT_SPINCONTROL_FLOAT:
+            minw = FloatWidth(spincontrol->min.f, spincontrol->step.f);
+            maxw = FloatWidth(spincontrol->max.f, spincontrol->step.f);
+            break;
+
+        default:
+        case TXT_SPINCONTROL_INT:
+            minw = IntWidth(spincontrol->min.i);
+            maxw = IntWidth(spincontrol->max.i);
+            break;
+
+    }

     // Choose the wider of the two values.  Add one so that there is always
     // space for the cursor when editing.
@@ -74,10 +125,26 @@ static void TXT_SpinControlSizeCalc(TXT_UNCAST_ARG(spincontrol))
     spincontrol->widget.h = 1;
 }

+static void SetBuffer(txt_spincontrol_t *spincontrol)
+{
+    char format[25];
+
+    switch (spincontrol->type)
+    {
+        case TXT_SPINCONTROL_INT:
+            sprintf(spincontrol->buffer, "%i", spincontrol->value->i);
+            break;
+
+        case TXT_SPINCONTROL_FLOAT:
+            FloatFormatString(spincontrol->step.f, format);
+            sprintf(spincontrol->buffer, format, spincontrol->value->f);
+            break;
+    }
+}
+
 static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol), int selected)
 {
     TXT_CAST_ARG(txt_spincontrol_t, spincontrol);
-    char buf[15];
     unsigned int i;
     unsigned int padding;

@@ -103,18 +170,14 @@ static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol), int selected)
         TXT_BGColor(TXT_COLOR_BLUE, 0);
     }

-    if (spincontrol->editing)
-    {
-        strcpy(buf, spincontrol->buffer);
-    }
-    else
+    if (!spincontrol->editing)
     {
-        sprintf(buf, "%i", *spincontrol->value);
+        SetBuffer(spincontrol);
     }
-
+
     i = 0;

-    padding = spincontrol->widget.w - strlen(buf) - 4;
+    padding = spincontrol->widget.w - strlen(spincontrol->buffer) - 4;

     while (i < padding)
     {
@@ -122,8 +185,8 @@ static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol), int selected)
         ++i;
     }

-    TXT_DrawString(buf);
-    i += strlen(buf);
+    TXT_DrawString(spincontrol->buffer);
+    i += strlen(spincontrol->buffer);

     while (i < spincontrol->widget.w - 4)
     {
@@ -162,10 +225,22 @@ static void Backspace(txt_spincontrol_t *spincontrol)

 static void EnforceLimits(txt_spincontrol_t *spincontrol)
 {
-    if (*spincontrol->value > spincontrol->max)
-        *spincontrol->value = spincontrol->max;
-    else if (*spincontrol->value < spincontrol->min)
-        *spincontrol->value = spincontrol->min;
+    switch (spincontrol->type)
+    {
+        case TXT_SPINCONTROL_INT:
+            if (spincontrol->value->i > spincontrol->max.i)
+                spincontrol->value->i = spincontrol->max.i;
+            else if (spincontrol->value->i < spincontrol->min.i)
+                spincontrol->value->i = spincontrol->min.i;
+            break;
+
+        case TXT_SPINCONTROL_FLOAT:
+            if (spincontrol->value->f > spincontrol->max.f)
+                spincontrol->value->f = spincontrol->max.f;
+            else if (spincontrol->value->f < spincontrol->min.f)
+                spincontrol->value->f = spincontrol->min.f;
+            break;
+    }
 }

 static int TXT_SpinControlKeyPress(TXT_UNCAST_ARG(spincontrol), int key)
@@ -178,7 +253,17 @@ static int TXT_SpinControlKeyPress(TXT_UNCAST_ARG(spincontrol), int key)
     {
         if (key == KEY_ENTER)
         {
-            *spincontrol->value = atoi(spincontrol->buffer);
+            switch (spincontrol->type)
+            {
+                case TXT_SPINCONTROL_INT:
+                    spincontrol->value->i = atoi(spincontrol->buffer);
+                    break;
+
+                case TXT_SPINCONTROL_FLOAT:
+                    spincontrol->value->f = (float) atof(spincontrol->buffer);
+                    break;
+            }
+
             spincontrol->editing = 0;
             EnforceLimits(spincontrol);
             return 1;
@@ -191,7 +276,7 @@ static int TXT_SpinControlKeyPress(TXT_UNCAST_ARG(spincontrol), int key)
             return 1;
         }

-        if (isdigit(key) || key == '-')
+        if (isdigit(key) || key == '-' || key == '.')
         {
             AddCharacter(spincontrol, key);
             return 1;
@@ -209,13 +294,22 @@ static int TXT_SpinControlKeyPress(TXT_UNCAST_ARG(spincontrol), int key)

         if (key == KEY_ENTER)
         {
-            sprintf(spincontrol->buffer, "%i", *spincontrol->value);
             spincontrol->editing = 1;
+            SetBuffer(spincontrol);
             return 1;
         }
         if (key == KEY_LEFTARROW)
         {
-            --*spincontrol->value;
+            switch (spincontrol->type)
+            {
+                case TXT_SPINCONTROL_INT:
+                    spincontrol->value->i -= spincontrol->step.i;
+                    break;
+
+                case TXT_SPINCONTROL_FLOAT:
+                    spincontrol->value->f -= spincontrol->step.f;
+                    break;
+            }

             EnforceLimits(spincontrol);

@@ -224,7 +318,16 @@ static int TXT_SpinControlKeyPress(TXT_UNCAST_ARG(spincontrol), int key)

         if (key == KEY_RIGHTARROW)
         {
-            ++*spincontrol->value;
+            switch (spincontrol->type)
+            {
+                case TXT_SPINCONTROL_INT:
+                    spincontrol->value->i += spincontrol->step.i;
+                    break;
+
+                case TXT_SPINCONTROL_FLOAT:
+                    spincontrol->value->f += spincontrol->step.f;
+                    break;
+            }

             EnforceLimits(spincontrol);

@@ -263,21 +366,45 @@ txt_widget_class_t txt_spincontrol_class =
     NULL,
 };

-txt_spincontrol_t *TXT_NewSpinControl(int *value, int min, int max)
+static txt_spincontrol_t *TXT_BaseSpinControl(void)
 {
     txt_spincontrol_t *spincontrol;

     spincontrol = malloc(sizeof(txt_spincontrol_t));

     TXT_InitWidget(spincontrol, &txt_spincontrol_class);
-    spincontrol->value = value;
-    spincontrol->min = min;
-    spincontrol->max = max;
-    spincontrol->buffer = malloc(15);
+    spincontrol->buffer = malloc(25);
     strcpy(spincontrol->buffer, "");
     spincontrol->editing = 0;

     return spincontrol;
 }

+txt_spincontrol_t *TXT_NewSpinControl(int *value, int min, int max)
+{
+    txt_spincontrol_t *spincontrol;
+
+    spincontrol = TXT_BaseSpinControl();
+    spincontrol->type = TXT_SPINCONTROL_INT;
+    spincontrol->value = (void *) value;
+    spincontrol->min.i = min;
+    spincontrol->max.i = max;
+    spincontrol->step.i = 1;
+
+    return spincontrol;
+}
+
+txt_spincontrol_t *TXT_NewFloatSpinControl(float *value, float min, float max)
+{
+    txt_spincontrol_t *spincontrol;
+
+    spincontrol = TXT_BaseSpinControl();
+    spincontrol->type = TXT_SPINCONTROL_FLOAT;
+    spincontrol->value = (void *) value;
+    spincontrol->min.f = min;
+    spincontrol->max.f = max;
+    spincontrol->step.f = 0.1;
+
+    return spincontrol;
+}

diff --git a/textscreen/txt_spinctrl.h b/textscreen/txt_spinctrl.h
index b3436ac7..2fdd2a62 100644
--- a/textscreen/txt_spinctrl.h
+++ b/textscreen/txt_spinctrl.h
@@ -23,19 +23,25 @@
 #define TXT_SPINCONTROL_H

 typedef struct txt_spincontrol_s txt_spincontrol_t;
+typedef enum
+{
+    TXT_SPINCONTROL_INT,
+    TXT_SPINCONTROL_FLOAT,
+} txt_spincontrol_type_t;

 #include "txt_widget.h"

 struct txt_spincontrol_s
 {
     txt_widget_t widget;
-    int min, max;
-    int *value;
+    txt_spincontrol_type_t type;
+    union { float f; int i; } min, max, *value, step;
     int editing;
     char *buffer;
 };

 txt_spincontrol_t *TXT_NewSpinControl(int *value, int min, int max);
+txt_spincontrol_t *TXT_NewFloatSpinControl(float *value, float min, float max);

 #endif /* #ifndef TXT_SPINCONTROL_H */