Я реализую модуль гибкой коробки CSS3 , как это определено в W3C, который аналогичен блочной модели Mozilla для xul . Хотя эти стандарты определяют, как должна вести себя модель, они не дают никаких подробностей о том, как они должны быть реализованы.
Детали интересующей меня модели:
- Коробки имеют ширину и высоту.
- Ящики могут содержать другие ящики.
- Контейнерные ящики (родительские ящики) отвечают за определение размера и расположение ящиков, которые они содержат (дочерние ящики).
- Коробки имеют ориентацию, которая может быть горизонтальной или вертикальной. Ориентация определяет, как дочерние блоки позиционируются и изменяются в размерах.
- Дочерние ящики могут быть гибкими или негибкими. Если дочерний блок негибкий, он рисуется в размере, указанном в параметрах width и height. Если он гибкий, то его размер изменяется в соответствии с доступным пространством в родительском контейнере.
- Гибкость относительно других дочерних ящиков в том же контейнере, размеры ящиков с более высокой гибкостью больше, чем у ящиков с меньшей гибкостью.
- Дочерние ящики могут быть ограничены минимальным или максимальным размером. Если дочерний блок является гибким, родительский блок никогда не изменит его размер ниже минимального размера или выше максимального размера.
Возможности 1-5 могут быть реализованы довольно эффективно. Функция 6 проблематична, так как самый эффективный алгоритм, который я могу придумать, довольно наивен. Алгоритм работает следующим образом:
- Поместите все поля в список.
- Переберите каждый дочерний блок и измените его размер, используя гибкость, чтобы определить сумму для его изменения.
- Если размер превышает одно из ограничений, установите для размера ячейки ограничение, удалите его из списка и начните с начала списка.
Шаг 3, где эффективность падает. Например, если в списке десять элементов, а последний имеет ограничение, то алгоритм вычисляет размер для первых девяти элементов, а затем, когда он достигает десятого элемента, ему необходимо повторить все вычисления. Я рассмотрел сохранение списка отсортированным и сначала определил размеры всех ограниченных блоков, однако это связано с дополнительными сложностями и накладными расходами на сортировку списка.
Я ожидаю, что существует признанное оптимальное решение, учитывая, что это довольно распространенная функция в браузерах и средах (XUL, .Net, Flex и т. Д.).