]> git.decadent.org.uk Git - ion3.git/blob - ioncore/float-placement.c
[svn-upgrade] Integrating new upstream version, ion3 (20070203)
[ion3.git] / ioncore / float-placement.c
1 /*
2  * ion/ioncore/float-placement.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
5  *
6  * Ion is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  */
11
12 #include <string.h>
13
14 #include "common.h"
15 #include "group.h"
16 #include "float-placement.h"
17
18
19 WFloatPlacement ioncore_placement_method=PLACEMENT_LRUD;
20
21
22 static void random_placement(WRectangle box, WRectangle *g)
23 {
24     box.w-=g->w;
25     box.h-=g->h;
26     g->x=box.x+(box.w<=0 ? 0 : rand()%box.w);
27     g->y=box.y+(box.h<=0 ? 0 : rand()%box.h);
28 }
29
30
31 static void ggeom(WRegion *reg, WRectangle *geom)
32 {
33     *geom=REGION_GEOM(reg);
34 }
35
36
37 #define IGNORE_ST(ST, WS) ((ST)->reg==NULL || (ST)==(WS)->bottom)
38
39 static WRegion* is_occupied(WGroup *ws, const WRectangle *r)
40 {
41     WGroupIterTmp tmp;
42     WStacking *st;
43     WRectangle p;
44     
45     FOR_ALL_NODES_IN_GROUP(ws, st, tmp){
46         if(IGNORE_ST(st, ws))
47             continue;
48         
49         ggeom(st->reg, &p);
50         
51         if(r->x>=p.x+p.w)
52             continue;
53         if(r->y>=p.y+p.h)
54             continue;
55         if(r->x+r->w<=p.x)
56             continue;
57         if(r->y+r->h<=p.y)
58             continue;
59         return st->reg;
60     }
61     
62     return NULL;
63 }
64
65
66 static int next_least_x(WGroup *ws, int x)
67 {
68     WRectangle p;
69     int retx=REGION_GEOM(ws).x+REGION_GEOM(ws).w;
70     WGroupIterTmp tmp;
71     WStacking *st;
72     
73     FOR_ALL_NODES_IN_GROUP(ws, st, tmp){
74         if(IGNORE_ST(st, ws))
75             continue;
76         
77         ggeom(st->reg, &p);
78         
79         if(p.x+p.w>x && p.x+p.w<retx)
80             retx=p.x+p.w;
81     }
82     
83     return retx+1;
84 }
85
86
87 static int next_lowest_y(WGroup *ws, int y)
88 {
89     WRectangle p;
90     int rety=REGION_GEOM(ws).y+REGION_GEOM(ws).h;
91     WGroupIterTmp tmp;
92     WStacking *st;
93     
94     FOR_ALL_NODES_IN_GROUP(ws, st, tmp){
95         if(IGNORE_ST(st, ws))
96             continue;
97         
98         ggeom(st->reg, &p);
99         
100         if(p.y+p.h>y && p.y+p.h<rety)
101             rety=p.y+p.h;
102     }
103     
104     return rety+1;
105 }
106
107
108 static bool tiling_placement(WGroup *ws, WRectangle *g)
109 {
110     WRegion *p;
111     WRectangle r, r2;
112     int maxx, maxy;
113     
114     r=REGION_GEOM(ws);
115     r.w=g->w;
116     r.h=g->h;
117
118     maxx=REGION_GEOM(ws).x+REGION_GEOM(ws).w;
119     maxy=REGION_GEOM(ws).y+REGION_GEOM(ws).h;
120     
121     if(ioncore_placement_method==PLACEMENT_UDLR){
122         while(r.x<maxx){
123             p=is_occupied(ws, &r);
124             while(p!=NULL && r.y+r.h<maxy){
125                 ggeom(p, &r2);
126                 r.y=r2.y+r2.h+1;
127                 p=is_occupied(ws, &r);
128             }
129             if(r.y+r.h<maxy && r.x+r.w<maxx){
130                 g->x=r.x;
131                 g->y=r.y;
132                 return TRUE;
133             }else{
134                 r.x=next_least_x(ws, r.x);
135                 r.y=0;
136             }
137         }
138     }else{
139         while(r.y<maxy){
140             p=is_occupied(ws, &r);
141             while(p!=NULL && r.x+r.w<maxx){
142                 ggeom(p, &r2);
143                 r.x=r2.x+r2.w+1;
144                 p=is_occupied(ws, &r);
145             }
146             if(r.y+r.h<maxy && r.x+r.w<maxx){
147                 g->x=r.x;
148                 g->y=r.y;
149                 return TRUE;
150             }else{
151                 r.y=next_lowest_y(ws, r.y);
152                 r.x=0;
153             }
154         }
155     }
156
157     return FALSE;
158
159 }
160
161
162 void group_calc_placement(WGroup *ws, WRectangle *geom)
163 {
164     if(ioncore_placement_method!=PLACEMENT_RANDOM){
165         if(tiling_placement(ws, geom))
166             return;
167     }
168     random_placement(REGION_GEOM(ws), geom);
169 }
170