massive update, probably broken
[dotfiles/.git] / .config / awesome / lain / layout / termfair.lua
1 --[[
2
3      Licensed under GNU General Public License v2
4       * (c) 2014,      projektile
5       * (c) 2013,      Luca CPZ
6       * (c) 2010,      Nicolas Estibals
7       * (c) 2010-2012, Peter Hofmann
8
9 --]]
10
11 local math     = math
12 local screen   = screen
13 local tonumber = tonumber
14
15 local termfair  = { name = "termfair" }
16 termfair.center = { name = "centerfair" }
17
18 local function do_fair(p, orientation)
19     local t = p.tag or screen[p.screen].selected_tag
20     local wa = p.workarea
21     local cls = p.clients
22
23     if #cls == 0 then return end
24
25     if orientation == "west" then
26         -- Layout with fixed number of vertical columns (read from nmaster).
27         -- New windows align from left to right. When a row is full, a now
28         -- one above it is created. Like this:
29
30         --        (1)                (2)                (3)
31         --   +---+---+---+      +---+---+---+      +---+---+---+
32         --   |   |   |   |      |   |   |   |      |   |   |   |
33         --   | 1 |   |   |  ->  | 2 | 1 |   |  ->  | 3 | 2 | 1 |  ->
34         --   |   |   |   |      |   |   |   |      |   |   |   |
35         --   +---+---+---+      +---+---+---+      +---+---+---+
36
37         --        (4)                (5)                (6)
38         --   +---+---+---+      +---+---+---+      +---+---+---+
39         --   | 4 |   |   |      | 5 | 4 |   |      | 6 | 5 | 4 |
40         --   +---+---+---+  ->  +---+---+---+  ->  +---+---+---+
41         --   | 3 | 2 | 1 |      | 3 | 2 | 1 |      | 3 | 2 | 1 |
42         --   +---+---+---+      +---+---+---+      +---+---+---+
43
44         -- How many vertical columns? Read from nmaster on the tag.
45         local num_x = tonumber(termfair.nmaster) or t.master_count
46         local ncol  = tonumber(termfair.ncol) or t.column_count
47
48         if num_x <= 2 then num_x = 2 end
49         if ncol  <= 1 then ncol  = 1 end
50         local width = math.floor(wa.width/num_x)
51
52         local num_y     = math.max(math.ceil(#cls / num_x), ncol)
53         local height    = math.floor(wa.height/num_y)
54         local cur_num_x = num_x
55         local at_x      = 0
56         local at_y      = 0
57
58         local remaining_clients = #cls
59
60         -- We start the first row. Left-align by limiting the number of
61         -- available slots.
62         if remaining_clients < num_x then
63             cur_num_x = remaining_clients
64         end
65
66         -- Iterate in reversed order.
67         for i = #cls,1,-1 do
68             -- Get x and y position.
69             local c = cls[i]
70             local this_x = cur_num_x - at_x - 1
71             local this_y = num_y - at_y - 1
72
73             -- Calculate geometry.
74             local g = {}
75             if this_x == (num_x - 1) then
76                 g.width = wa.width - (num_x - 1)*width
77             else
78                 g.width = width
79             end
80
81             if this_y == (num_y - 1) then
82                 g.height = wa.height - (num_y - 1)*height
83             else
84                 g.height = height
85             end
86
87             g.x = wa.x + this_x*width
88             g.y = wa.y + this_y*height
89
90             if g.width  < 1 then g.width  = 1 end
91             if g.height < 1 then g.height = 1 end
92
93             p.geometries[c] = g
94
95             remaining_clients = remaining_clients - 1
96
97             -- Next grid position.
98             at_x = at_x + 1
99             if at_x == num_x then
100                 -- Row full, create a new one above it.
101                 at_x = 0
102                 at_y = at_y + 1
103
104                 -- We start a new row. Left-align.
105                 if remaining_clients < num_x then
106                     cur_num_x = remaining_clients
107                 end
108             end
109         end
110     elseif orientation == "center" then
111         -- Layout with fixed number of vertical columns (read from nmaster).
112         -- Cols are centerded until there is nmaster columns, then windows
113         -- are stacked in the slave columns, with at most ncol clients per
114         -- column if possible.
115
116         -- with nmaster=3 and ncol=1 you'll have
117         --        (1)                (2)                (3)
118         --   +---+---+---+      +-+---+---+-+      +---+---+---+
119         --   |   |   |   |      | |   |   | |      |   |   |   |
120         --   |   | 1 |   |  ->  | | 1 | 2 | | ->   | 1 | 2 | 3 |  ->
121         --   |   |   |   |      | |   |   | |      |   |   |   |
122         --   +---+---+---+      +-+---+---+-+      +---+---+---+
123
124         --        (4)                (5)
125         --   +---+---+---+      +---+---+---+
126         --   |   |   | 3 |      |   | 2 | 4 |
127         --   + 1 + 2 +---+  ->  + 1 +---+---+
128         --   |   |   | 4 |      |   | 3 | 5 |
129         --   +---+---+---+      +---+---+---+
130
131         -- How many vertical columns? Read from nmaster on the tag.
132         local num_x = tonumber(termfair.center.nmaster) or t.master_count
133         local ncol  = tonumber(termfair.center.ncol) or t.column_count
134
135         if num_x <= 2 then num_x = 2 end
136         if ncol  <= 1 then ncol  = 1 end
137
138         local width = math.floor(wa.width / num_x)
139
140         if #cls < num_x then
141             -- Less clients than the number of columns, let's center it!
142             local offset_x = wa.x + (wa.width - #cls*width) / 2
143             for i = 1, #cls do
144                 local g = { y = wa.y }
145                 g.width  = width
146                 g.height = wa.height
147                 if g.width < 1 then g.width = 1 end
148                 if g.height < 1 then g.height = 1 end
149                 g.x = offset_x + (i - 1) * width
150                 p.geometries[cls[i]] = g
151             end
152         else
153             -- More clients than the number of columns, let's arrange it!
154             -- Master client deserves a special treatement
155             local g = {}
156             g.width = wa.width - (num_x - 1)*width
157             g.height = wa.height
158             if g.width < 1 then g.width = 1 end
159             if g.height < 1 then g.height = 1 end
160             g.x = wa.x
161             g.y = wa.y
162             p.geometries[cls[1]] = g
163
164             -- Treat the other clients
165
166             -- Compute distribution of clients among columns
167             local num_y = {}
168             local remaining_clients = #cls-1
169             local ncol_min = math.ceil(remaining_clients/(num_x-1))
170
171             if ncol >= ncol_min then
172                 for i = (num_x-1), 1, -1 do
173                     if (remaining_clients-i+1) < ncol then
174                         num_y[i] = remaining_clients-i + 1
175                     else
176                         num_y[i] = ncol
177                     end
178                     remaining_clients = remaining_clients - num_y[i]
179                 end
180             else
181                 local rem = remaining_clients % (num_x-1)
182                 if rem == 0 then
183                     for i = 1, num_x-1 do
184                         num_y[i] = ncol_min
185                     end
186                 else
187                     for i = 1, num_x-1 do
188                         num_y[i] = ncol_min - 1
189                     end
190                     for i = 0, rem-1 do
191                         num_y[num_x-1-i] = num_y[num_x-1-i] + 1
192                     end
193                 end
194             end
195
196             -- Compute geometry of the other clients
197             local nclient = 2 -- we start with the 2nd client
198             local wx = g.x + g.width
199             for i = 1, (num_x-1) do
200                 local height = math.floor(wa.height / num_y[i])
201                 local wy = wa.y
202                 for j = 0, (num_y[i]-2) do
203                     local g = {}
204                     g.x = wx
205                     g.y = wy
206                     g.height = height
207                     g.width = width
208                     if g.width < 1 then g.width = 1 end
209                     if g.height < 1 then g.height = 1 end
210                     p.geometries[cls[nclient]] = g
211                     nclient = nclient + 1
212                     wy = wy + height
213                 end
214                 local g = {}
215                 g.x = wx
216                 g.y = wy
217                 g.height = wa.height - (num_y[i] - 1)*height
218                 g.width = width
219                 if g.width < 1 then g.width = 1 end
220                 if g.height < 1 then g.height = 1 end
221                 p.geometries[cls[nclient]] = g
222                 nclient = nclient + 1
223                 wx = wx + width
224             end
225         end
226     end
227 end
228
229 function termfair.center.arrange(p)
230     return do_fair(p, "center")
231 end
232
233 function termfair.arrange(p)
234     return do_fair(p, "west")
235 end
236
237 return termfair