Re: [AD] new GUI focus selection algorithm

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


On Wed, 2003-11-12 at 13:43, Elias Pschernig wrote:

> Where going up down from F/D wouldn't work. So, basically, just take the
> original algorithm, and use the 'closest distance'. I'll try and
> implement it until sometime in the weekend - should be much more simple
> than my collision approach :P
> 

Ok, the attached patch implements it. Instead of using 0x10000 when
wrapping around at the edges, I used SCREEN_W and SCREEN_H - since we
already know that 'screen' is the bitmap the GUI is drawn to, I think
this is quite a safe assumption about the GUI size.

Anyway, my thoughts about it:

Both the collision and the new distance algorithm are better than the
original, simply because the original completely ignores w and h.

The behavior from the collision algorithm can be closer to the original
in case dialogs are ordered in left aligned columns, which probably is
the case quite often. The new distance formula will cause jumps to
another column quite easily, like:

AAA 
BBB  
    E
CCC F
DDD G

Here, going down from B will jump to E and not to C like in the
collision approach, and also in the original formula. And in general,
the closest distance jumps around too much for my taste, also jumping
over other buttons:

    CCC 
  BBB
AAA     DDD

Going right from A jumps to C, since B is not to the right of A. The
collision approach of course never can jump and would go to D, and
somehow behaves more predictable, at least to me :) And as Sven's circle
example shows, there will always be unreachable buttons, since we have
only 4 arrow keys, for unlimited possible directions to the next
rectangle.

Anyway, I don't care which/if it is changed to, it's really not an
important feature and not very many will ever notice it..

-- 
Elias Pschernig <elias@xxxxxxxxxx>
Index: src/gui.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/gui.c,v
retrieving revision 1.65
diff -u -r1.65 gui.c
--- src/gui.c	17 Oct 2003 08:49:18 -0000	1.65
+++ src/gui.c	16 Nov 2003 14:51:53 -0000
@@ -23,6 +23,7 @@
 
 
 #include <limits.h>
+#include <math.h>
 
 #include "allegro.h"
 #include "allegro/internal/aintern.h"
@@ -547,17 +548,58 @@
 
 
 
+/* min_dist:
+ *  Get the minimum distance from a dialog to a rectangle.
+ */
+static int min_dist(AL_CONST DIALOG *d1, int d2x, int d2y, int d2w, int d2h)
+{
+   int x_left = d1->x - d2x - d2w + 1;
+   int x_right = d2x - d1->x - d1->w + 1;
+   int y_top = d1->y - d2y - d2h + 1;
+   int y_bottom = d2y - d1->y - d1->h + 1;
+
+   if (x_left > 0) { /* d2 is left of d1 */
+       if (y_top > 0) { /* d2 is above d1 */
+           return sqrt(x_left * x_left + y_top * y_top);
+       }
+       if (y_bottom > 0) { /* d2 is below d1 */
+           return sqrt(x_left * x_left + y_bottom * y_bottom);
+       }
+       /* vertically overlapping */
+       return x_left;
+   }
+   if (x_right > 0) { /* d2 is right of d1 */
+       if (y_top > 0) { /* d2 is above d1 */
+           return sqrt(x_right * x_right + y_top * y_top);
+       }
+       if (y_bottom > 0) { /* d2 is below d1 */
+           return sqrt(x_right * x_right + y_bottom * y_bottom);
+       }
+       /* vertically overlapping */
+       return x_right;
+   }
+   /* horizontally overlapping */
+   if (y_top > 0) { /* d2 is above d1 */
+       return y_top;
+   }
+   if (y_bottom > 0) { /* d2 is below d1 */
+       return y_bottom;
+   }
+   /* overlapping */
+   return 0;
+}
+
+
+
 /* cmp_right:
  *  Comparison function for right arrow key movement.
  */
 static int cmp_right(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2)
 {
-   int ret = (d2->x - d1->x) + ABS(d1->y - d2->y) * 8;
-
-   if (d1->x >= d2->x)
-      ret += 0x10000;
-
-   return ret;
+   if (d1->x + d1->w > d2->x)
+       return min_dist(d1, SCREEN_W + d2->x, d2->y, d2->w, d2->h);
+   else
+       return  min_dist(d1, d2->x, d2->y, d2->w, d2->h);
 }
 
 
@@ -567,12 +609,10 @@
  */
 static int cmp_left(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2)
 {
-   int ret = (d1->x - d2->x) + ABS(d1->y - d2->y) * 8;
-
-   if (d1->x <= d2->x)
-      ret += 0x10000;
-
-   return ret;
+   if (d1->x < d2->x + d2->w)
+      return  min_dist(d1, d2->x - SCREEN_W, d2->y, d2->w, d2->h); 
+   else
+      return  min_dist(d1, d2->x, d2->y, d2->w, d2->h); 
 }
 
 
@@ -582,12 +622,10 @@
  */
 static int cmp_down(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2)
 {
-   int ret = (d2->y - d1->y) + ABS(d1->x - d2->x) * 8;
-
-   if (d1->y >= d2->y)
-      ret += 0x10000;
-
-   return ret;
+   if (d1->y + d1->h > d2->y)
+       return min_dist(d1, d2->x, SCREEN_H + d2->y, d2->w, d2->h);
+   else
+       return  min_dist(d1, d2->x, d2->y, d2->w, d2->h);
 }
 
 
@@ -597,12 +635,10 @@
  */
 static int cmp_up(AL_CONST DIALOG *d1, AL_CONST DIALOG *d2)
 {
-   int ret = (d1->y - d2->y) + ABS(d1->x - d2->x) * 8;
-
-   if (d1->y <= d2->y)
-      ret += 0x10000;
-
-   return ret;
+   if (d1->y < d2->y + d2->h)
+       return min_dist(d1, d2->x, d2->y - SCREEN_H, d2->w, d2->h);
+   else
+       return  min_dist(d1, d2->x, d2->y, d2->w, d2->h); 
 }
 
 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/