1 /******************************************************************************* 2 * Copyright (c) 2000, 2008 IBM Corporation and others. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * IBM Corporation - initial API and implementation 10 * Port to the D programming language: 11 * Frank Benoit <benoit@tionex.de> 12 *******************************************************************************/ 13 module org.eclipse.swt.layout.FormAttachment; 14 15 import org.eclipse.swt.SWT; 16 import org.eclipse.swt.widgets.Control; 17 import org.eclipse.swt.layout.FormLayout; 18 import org.eclipse.swt.layout.FormData; 19 20 import java.lang.all; 21 22 /** 23 * Instances of this class are used to define the edges of a control 24 * within a <code>FormLayout</code>. 25 * <p> 26 * <code>FormAttachments</code> are set into the top, bottom, left, 27 * and right fields of the <code>FormData</code> for a control. 28 * For example: 29 * <pre> 30 * FormData data = new FormData(); 31 * data.top = new FormAttachment(0,5); 32 * data.bottom = new FormAttachment(100,-5); 33 * data.left = new FormAttachment(0,5); 34 * data.right = new FormAttachment(100,-5); 35 * button.setLayoutData(data); 36 * </pre> 37 * </p> 38 * <p> 39 * A <code>FormAttachment</code> defines where to attach the side of 40 * a control by using the equation, y = ax + b. The "a" term represents 41 * a fraction of the parent composite's width (from the left) or height 42 * (from the top). It can be defined using a numerator and denominator, 43 * or just a percentage value. If a percentage is used, the denominator 44 * is set to 100. The "b" term in the equation represents an offset, in 45 * pixels, from the attachment position. For example: 46 * <pre> 47 * FormAttachment attach = new FormAttachment (20, -5); 48 * </pre> 49 * specifies that the side to which the <code>FormAttachment</code> 50 * object belongs will lie at 20% of the parent composite, minus 5 pixels. 51 * </p> 52 * <p> 53 * Control sides can also be attached to another control. 54 * For example: 55 * <pre> 56 * FormAttachment attach = new FormAttachment (button, 10); 57 * </pre> 58 * specifies that the side to which the <code>FormAttachment</code> 59 * object belongs will lie in the same position as the adjacent side of 60 * the <code>button</code> control, plus 10 pixels. The control side can 61 * also be attached to the opposite side of the specified control. 62 * For example: 63 * <pre> 64 * FormData data = new FormData (); 65 * data.left = new FormAttachment (button, 0, SWT.LEFT); 66 * </pre> 67 * specifies that the left side of the control will lie in the same position 68 * as the left side of the <code>button</code> control. The control can also 69 * be attached in a position that will center the control on the specified 70 * control. For example: 71 * <pre> 72 * data.left = new FormAttachment (button, 0, SWT.CENTER); 73 * </pre> 74 * specifies that the left side of the control will be positioned so that it is 75 * centered between the left and right sides of the <code>button</code> control. 76 * If the alignment is not specified, the default is to attach to the adjacent side. 77 * </p> 78 * 79 * @see FormLayout 80 * @see FormData 81 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> 82 * 83 * @since 2.0 84 */ 85 public final class FormAttachment { 86 /** 87 * numerator specifies the numerator of the "a" term in the 88 * equation, y = ax + b, which defines the attachment. 89 */ 90 public int numerator; 91 92 /** 93 * denominator specifies the denominator of the "a" term in the 94 * equation, y = ax + b, which defines the attachment. 95 * 96 * The default value is 100. 97 */ 98 public int denominator = 100; 99 100 /** 101 * offset specifies the offset, in pixels, of the control side 102 * from the attachment position. 103 * If the offset is positive, then the control side is offset 104 * to the right of or below the attachment position. If it is 105 * negative, then the control side is offset to the left of or 106 * above the attachment position. 107 * 108 * This is equivalent to the "b" term in the equation y = ax + b. 109 * The default value is 0. 110 */ 111 public int offset; 112 113 /** 114 * control specifies the control to which the control side is 115 * attached. 116 */ 117 public Control control; 118 119 /** 120 * alignment specifies the alignment of the control side that is 121 * attached to a control. 122 * <p> 123 * For top and bottom attachments, TOP, BOTTOM and CENTER are used. For left 124 * and right attachments, LEFT, RIGHT and CENTER are used. If any other case 125 * occurs, the default will be used instead. 126 * </p> 127 * 128 * <br>Possible values are: <ul> 129 * <li>{@link SWT#TOP}: Attach the side to the top side of the specified control.</li> 130 * <li>{@link SWT#BOTTOM}: Attach the side to the bottom side of the specified control.</li> 131 * <li>{@link SWT#LEFT}: Attach the side to the left side of the specified control.</li> 132 * <li>{@link SWT#RIGHT}: Attach the side to the right side of the specified control.</li> 133 * <li>{@link SWT#CENTER}: Attach the side at a position which will center the control on the specified control.</li> 134 * <li>{@link SWT#DEFAULT}: Attach the side to the adjacent side of the specified control.</li> 135 * </ul> 136 */ 137 public int alignment; 138 139 /** 140 * Constructs a new instance of this class. 141 * Since no numerator, denominator or offset is specified, 142 * the attachment is treated as a percentage of the form. 143 * The numerator is zero, the denominator is 100 and the 144 * offset is zero. 145 * 146 * @since 3.2 147 */ 148 public this () { 149 } 150 151 /** 152 * Constructs a new instance of this class given a numerator 153 * Since no denominator or offset is specified, the default 154 * is to treat the numerator as a percentage of the form, with a 155 * denominator of 100. The offset is zero. 156 * 157 * @param numerator the percentage of the position 158 * 159 * @since 3.0 160 */ 161 public this (int numerator) { 162 this (numerator, 100, 0); 163 } 164 165 /** 166 * Constructs a new instance of this class given a numerator 167 * and an offset. Since no denominator is specified, the default 168 * is to treat the numerator as a percentage of the form, with a 169 * denominator of 100. 170 * 171 * @param numerator the percentage of the position 172 * @param offset the offset of the side from the position 173 */ 174 public this (int numerator, int offset) { 175 this (numerator, 100, offset); 176 } 177 178 /** 179 * Constructs a new instance of this class given a numerator 180 * and denominator and an offset. The position of the side is 181 * given by the fraction of the form defined by the numerator 182 * and denominator. 183 * 184 * @param numerator the numerator of the position 185 * @param denominator the denominator of the position 186 * @param offset the offset of the side from the position 187 */ 188 public this (int numerator, int denominator, int offset) { 189 if (denominator is 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO); 190 this.numerator = numerator; 191 this.denominator = denominator; 192 this.offset = offset; 193 } 194 195 /** 196 * Constructs a new instance of this class given a control. 197 * Since no alignment is specified, the default alignment is 198 * to attach the side to the adjacent side of the specified 199 * control. Since no offset is specified, an offset of 0 is 200 * used. 201 * 202 * @param control the control the side is attached to 203 */ 204 public this (Control control) { 205 this (control, 0, SWT.DEFAULT); 206 } 207 208 /** 209 * Constructs a new instance of this class given a control 210 * and an offset. Since no alignment is specified, the default 211 * alignment is to attach the side to the adjacent side of the 212 * specified control. 213 * 214 * @param control the control the side is attached to 215 * @param offset the offset of the side from the control 216 */ 217 public this (Control control, int offset) { 218 this (control, offset, SWT.DEFAULT); 219 } 220 221 /** 222 * Constructs a new instance of this class given a control, 223 * an offset and an alignment. The possible alignment values are: 224 * <dl> 225 * <dt><b>{@link SWT#TOP}</b></dt> 226 * <dd>the side will be attached to the top side of the specified control</dd> 227 * <dt><b>{@link SWT#BOTTOM}</b></dt> 228 * <dd>the side will be attached to the bottom side of the specified control</dd> 229 * <dt><b>{@link SWT#LEFT}</b></dt> 230 * <dd>the side will be attached to the left side of the specified control</dd> 231 * <dt><b>{@link SWT#RIGHT}</b></dt> 232 * <dd>the side will be attached to the right side of the specified control</dd> 233 * <dt><b>{@link SWT#CENTER}</b></dt> 234 * <dd>the side will be centered on the same side of the specified control</dd> 235 * <dt><b>{@link SWT#DEFAULT}</b></dt> 236 * <dd>the side will be attached to the adjacent side of the specified control</dd> 237 * </dl> 238 * 239 * @param control the control the side is attached to 240 * @param offset the offset of the side from the control 241 * @param alignment the alignment of the side to the control it is attached to, 242 * one of TOP, BOTTOM, LEFT, RIGHT, CENTER, or DEFAULT 243 */ 244 public this (Control control, int offset, int alignment) { 245 this.control = control; 246 this.offset = offset; 247 this.alignment = alignment; 248 } 249 250 FormAttachment divide (int value) { 251 return new FormAttachment (numerator, denominator * value, offset / value); 252 } 253 254 int gcd (int m, int n) { 255 int temp; 256 m = Math.abs (m); 257 n = Math.abs (n); 258 if (m < n) { 259 temp = m; 260 m = n; 261 n = temp; 262 } 263 while (n !is 0){ 264 temp = m; 265 m = n; 266 n = temp % n; 267 } 268 return m; 269 } 270 271 FormAttachment minus (FormAttachment attachment) { 272 FormAttachment solution = new FormAttachment (); 273 solution.numerator = numerator * attachment.denominator - denominator * attachment.numerator; 274 solution.denominator = denominator * attachment.denominator; 275 int gcd = gcd (solution.denominator, solution.numerator); 276 solution.numerator = solution.numerator / gcd; 277 solution.denominator = solution.denominator / gcd; 278 solution.offset = offset - attachment.offset; 279 return solution; 280 } 281 282 FormAttachment minus (int value) { 283 return new FormAttachment (numerator, denominator, offset - value); 284 } 285 286 FormAttachment plus (FormAttachment attachment) { 287 FormAttachment solution = new FormAttachment (); 288 solution.numerator = numerator * attachment.denominator + denominator * attachment.numerator; 289 solution.denominator = denominator * attachment.denominator; 290 int gcd = gcd (solution.denominator, solution.numerator); 291 solution.numerator = solution.numerator / gcd; 292 solution.denominator = solution.denominator / gcd; 293 solution.offset = offset + attachment.offset; 294 return solution; 295 } 296 297 FormAttachment plus (int value) { 298 return new FormAttachment (numerator, denominator, offset + value); 299 } 300 301 int solveX (int value) { 302 if (denominator is 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO); 303 return ((numerator * value) / denominator) + offset; 304 } 305 306 int solveY (int value) { 307 if (numerator is 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO); 308 return (value - offset) * denominator / numerator; 309 } 310 311 /** 312 * Returns a string containing a concise, human-readable 313 * description of the receiver. 314 * 315 * @return a string representation of the FormAttachment 316 */ 317 public override String toString () { 318 String string = control !is null ? control.toString () : Format( "{}/{}", numerator, denominator ); 319 return Format("{{y = ({})x + {}}", string, ( offset >= 0 ? Format(")x + {}", offset ) : Format( ")x - {}", -offset))); 320 } 321 322 }