]> git.madduck.net Git - etc/awesome.git/blob - layout/termfair.lua

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

util/menu_iterator: unpack retro compatibility
[etc/awesome.git] / 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