1
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
3
* Copyright (C) 2011 Canonical Ltd
5
* This program is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 3 as
7
* published by the Free Software Foundation.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
* Authored by: Jason Smith <jason.smith@canonical.com>
20
#include "LayoutSystem.h"
21
#include "WindowManager.h"
26
LayoutSystem::LayoutSystem()
30
LayoutSystem::~LayoutSystem()
34
void LayoutSystem::LayoutWindows (LayoutWindowList windows, nux::Geometry const& max_bounds, nux::Geometry& final_bounds)
36
unsigned int size = windows.size();
41
for (auto window : windows)
43
window->geo = WindowManager::Default ()->GetWindowGeometry (window->xid);
44
window->aspect_ratio = (float)window->geo.width / (float)window->geo.height;
47
// we special case 2 and 3 since they are the most common
48
// cases (other than 1) and can be made beautiful with relative ease
52
LayoutTwoWindows (windows, max_bounds, final_bounds);
55
LayoutGridWindows (windows, max_bounds, final_bounds);
60
void LayoutSystem::LayoutTwoWindows (LayoutWindowList windows, nux::Geometry const& max_bounds, nux::Geometry& final_bounds)
62
LayoutWindow::Ptr first = windows[0];
63
LayoutWindow::Ptr second = windows[1];
65
float combined_aspect = first->aspect_ratio + second->aspect_ratio;
67
final_bounds = max_bounds;
69
if (combined_aspect >= 1.0f)
72
final_bounds.y += (final_bounds.height - (final_bounds.height / combined_aspect)) / 2;
73
final_bounds.height = final_bounds.height / combined_aspect;
75
first->result.x = final_bounds.x;
76
first->result.y = final_bounds.y;
77
first->result.height = final_bounds.height;
78
first->result.width = first->result.height * first->aspect_ratio;
80
second->result.x = final_bounds.x + first->result.width;
81
second->result.y = final_bounds.y;
82
second->result.height = final_bounds.height;
83
second->result.width = second->result.height * second->aspect_ratio;
85
else if (combined_aspect < 1.0f)
88
final_bounds.x += (final_bounds.width - (final_bounds.width / combined_aspect)) / 2;
89
final_bounds.width = final_bounds.width / combined_aspect;
92
first->result.x = final_bounds.x;
93
first->result.y = final_bounds.y;
94
first->result.height = final_bounds.height;
95
first->result.width = first->result.height * first->aspect_ratio;
97
second->result.x = final_bounds.x + first->result.width;
98
second->result.y = final_bounds.y;
99
second->result.height = final_bounds.height;
100
second->result.width = second->result.height * second->aspect_ratio;
104
void LayoutSystem::LayoutGridWindows (LayoutWindowList windows, nux::Geometry const& max_bounds, nux::Geometry& final_bounds)
109
while (width * height < (int) windows.size ())
117
final_bounds = max_bounds;
119
int block_width = final_bounds.width / width;
120
int block_height = final_bounds.height / height;
125
int start_x = final_bounds.x + final_bounds.width;
126
int start_y = final_bounds.y + final_bounds.height;
133
int block_x = start_x;
134
int block_y = start_y;
135
int vertical_offset = 0;
137
LayoutWindowList row_accum;
139
LayoutWindowList::reverse_iterator it;
140
for (it = windows.rbegin (); it != windows.rend (); it++)
143
window->result = ScaleBoxIntoBox (nux::Geometry (block_x - block_width, block_y - block_height, block_width, block_height), window->geo);
144
row_accum.push_back (window);
146
x1 = MIN (window->result.x, x1);
147
y1 = MIN (window->result.y, y1);
148
x2 = MAX (window->result.x + window->result.width, x2);
149
y2 = MAX (window->result.y + window->result.height, y2);
152
block_x -= block_width;
153
if (x >= width || x + y * width == (int) windows.size ())
161
block_width += (width * height - windows.size ()) * block_width / (windows.size () - width * (height - 1));
165
if (y2 >= block_y + block_height)
167
block_y -= block_height;
171
int this_savings = (y1 - (block_y - block_height)) * 2;
172
block_y = block_y - (block_height - this_savings);
174
for (auto w : row_accum)
175
w->result.y += this_savings / 2;
177
vertical_offset += this_savings / 2;
189
for (auto window : windows)
191
window->result.y -= vertical_offset;
193
x1 = MIN (window->result.x, x1);
194
y1 = MIN (window->result.y, y1);
195
x2 = MAX (window->result.x + window->result.width, x2);
196
y2 = MAX (window->result.y + window->result.height, y2);
199
final_bounds = nux::Geometry (x1, y1, x2 - x1, y2 - y1);
202
nux::Geometry LayoutSystem::ScaleBoxIntoBox (nux::Geometry const& bounds, nux::Geometry const& box)
204
float bound_aspect = (float) bounds.width / (float) bounds.height;
205
float box_aspect = (float) box.width / (float) box.height;
207
nux::Geometry result;
209
if (box_aspect > bound_aspect)
211
// box wider than bounds
214
result.width = bounds.width;
215
result.height = result.width / box_aspect;
217
result.y = bounds.y + (bounds.height - result.height) / 2;
223
result.height = bounds.height;
224
result.width = result.height * box_aspect;
226
result.x = bounds.x + (bounds.width - result.width) / 2;
232
LayoutWindow::LayoutWindow(Window xid)
b'\\ No newline at end of file'