The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

BoxLayout.vala in birdui

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of birdui/BoxLayout.vala.
Merge branch '2.x' of github.com:johanmattssonm/birdfont
1 /* 2 Copyright (C) 2016 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 15 using Gee; 16 using SvgBird; 17 using B; 18 using Cairo; 19 20 namespace Bird { 21 22 public enum BoxOrientation { 23 HORIZONTAL, 24 VERTICAL 25 } 26 27 class BoxLayout : Component { 28 29 public BoxOrientation orientation { get; private set; } 30 31 public BoxLayout (XmlElement layout_tag, BoxOrientation orientation, Defs defs) { 32 base (layout_tag, defs); 33 this.orientation = orientation; 34 } 35 36 public override void draw (Context cairo) { 37 cairo.save (); 38 cairo.translate (padded_x, padded_y); 39 clip (cairo); 40 41 foreach (Component component in components) { 42 component.draw (cairo); 43 } 44 45 cairo.restore (); 46 } 47 48 bool is_width_remainder (Component component) { 49 return component.style.property_equals ("width", "remainder"); 50 } 51 52 bool is_height_remainder (Component component) { 53 return component.style.property_equals ("height", "remainder"); 54 } 55 56 /** The smallest size this layout can be. */ 57 public override void get_min_size (out double min_width, out double min_height) { 58 min_width = 0; 59 min_height = 0; 60 61 if (orientation == BoxOrientation.HORIZONTAL) { 62 foreach (Component component in components) { 63 double w, h; 64 65 component.get_min_size (out w, out h); 66 min_width += w; 67 68 if (h > min_height) { 69 min_height = h; 70 } 71 } 72 } else { 73 foreach (Component component in components) { 74 double w, h; 75 76 component.get_min_size (out w, out h); 77 min_height += h; 78 79 if (w > min_width) { 80 min_width = w; 81 } 82 } 83 } 84 85 min_width += get_padding_left (); 86 min_width += get_padding_right (); 87 min_height += get_padding_top (); 88 min_height += get_padding_bottom (); 89 90 limit_size (ref min_width, ref min_height); 91 } 92 93 public override void layout (double parent_width, double parent_height) { 94 double w, h; 95 96 get_min_size (out w, out h); 97 int remainders = count_remainders (); 98 99 if (!is_width_remainder (this)) { 100 width = w; 101 } 102 103 if (!is_height_remainder (this)) { 104 height = h; 105 } 106 107 if (remainders > 0) { 108 double remainder_size; 109 110 if (orientation == BoxOrientation.HORIZONTAL) { 111 remainder_size = (parent_width - w) / remainders; 112 layout_variable_size (remainder_size, parent_height); 113 } else { 114 remainder_size = (parent_height - h) / remainders; 115 layout_variable_size (remainder_size, parent_width); 116 } 117 } 118 119 if (orientation == BoxOrientation.HORIZONTAL) { 120 foreach (Component component in components) { 121 component.layout (parent_width, h); 122 } 123 } else { 124 foreach (Component component in components) { 125 component.layout (w, parent_height); 126 } 127 } 128 129 layout_positions (); 130 } 131 132 int count_remainders () { 133 int remainders = 0; 134 135 if (orientation == BoxOrientation.HORIZONTAL) { 136 foreach (Component component in components) { 137 if (is_width_remainder (component)) { 138 remainders++; 139 } 140 } 141 } else { 142 foreach (Component component in components) { 143 if (is_height_remainder (component)) { 144 remainders++; 145 } 146 } 147 } 148 149 return remainders; 150 } 151 152 void layout_variable_size (double remainder_size, double fixed_size) { 153 double w, h; 154 155 w = 0; 156 h = 0; 157 foreach (Component component in components) { 158 bool width_remainder = is_width_remainder (component); 159 bool height_remainder = is_height_remainder (component); 160 161 if (width_remainder && orientation == BoxOrientation.HORIZONTAL) { 162 w = remainder_size; 163 w -= component.get_padding_left (); 164 w -= component.get_padding_right (); 165 h = fixed_size; 166 } 167 168 if (height_remainder && orientation == BoxOrientation.VERTICAL) { 169 w = fixed_size; 170 h = remainder_size; 171 h -= component.get_padding_top (); 172 h -= component.get_padding_bottom (); 173 } 174 175 if (width_remainder || height_remainder) { 176 double min_width, min_height; 177 component.get_min_size (out min_width, out min_height); 178 179 if (w < min_width) { 180 w = min_width; 181 } 182 183 if (h < min_height) { 184 h = min_height; 185 } 186 187 component.limit_size (ref w, ref h); 188 component.width = w; 189 component.height = h; 190 } 191 } 192 } 193 194 void layout_positions () { 195 double child_x = 0; 196 double child_y = 0; 197 198 foreach (Component component in components) { 199 component.x = child_x + component.get_padding_left (); 200 component.y = child_y + component.get_padding_top (); 201 202 if (orientation == BoxOrientation.HORIZONTAL) { 203 child_x = component.x + component.padded_width + get_padding_right (); 204 } else { 205 child_y = component.y + component.padded_height + get_padding_bottom (); 206 } 207 } 208 } 209 210 public override string to_string () { 211 return "BoxLayout"; 212 } 213 } 214 215 } 216