001package org.vishia.gral.base; 002 003import java.text.ParseException; 004 005import org.vishia.bridgeC.IllegalArgumentExceptionJc; 006import org.vishia.gral.ifc.GralRectangle; 007import org.vishia.util.Assert; 008import org.vishia.util.StringPart; 009import org.vishia.util.StringPartScan; 010 011 012/*Test with Jbat: call Jbat with this java file with its full path: 013D:/vishia/Java/srcJava_vishiaGui/org/vishia/gral/base/GralPos.java 014==JZcmd== 015java org.vishia.gral.base.GralPos.testScanSize(); 016==endJZcmd== 017*/ 018 019 020/**This class describes a position in a gral panel. 021 * <br><br> 022 * <b>Concept of positioning</b>:<br> 023 * The position are never given as pixel positions. They are user-oriented positions. The calculation 024 * of pixel units are done from the implementing graphic layer depending on the graphic device properties 025 * and the requested size appearance. The same graphic elements can be presented in several sizes 026 * on the display. 027 * <br><br> 028 * A normal text with a font in the standard proper read-able size is presented by 2 units of the Gral-position 029 * in vertical direction (line) and approximately 1 unit per character in horizontal direction. 030 * Of course the horizontal character size depends on the font properties. 031 * A text can be presented in a smaller or larger font. 032 * The text height depends on the height given in the position of the text. A very small font is presented by 1 vertical gral-unit. 033 * Such a text can be used as short title for text input fields (prompt) or adequate. 034 * <br> 035 * A button is able to proper present with 3 or 2 vertical gral units. A small check box may be presented 036 * with 1 x 1 gral unit. 037 * <br><br> 038 * A gral unit should be have the same distance in vertical as in horizontal direction. It depends on the 039 * graphical implementation. One gral unit may have approximately 6 to 30 pixel, 040 * depending on the requested size of appearance in comparison with the given display pixel size. 041 * Any graphic can be shown in several sizes of appearance, given with a start parameter of the application 042 * (see {@link org.vishia.gral.area9.GuiCallingArgs#sSize}) respectively the parameter size of {@link GralGridProperties#GralGridProperties(char size)}. 043 * <br><br> 044 * <b>Fine positions</b>:<br> 045 * Either the positions are given with 2 integer values as 'fundamental positions'. 046 * That are the position described above. 047 * Or they can be given with a float value or a second int named 'fractional part'. From the float value 048 * only the first digit after point is used, a fractional part can be given 049 * with a value from 0 to 9. 050 * <br><br> 051 * The fine position divides one gral position into 5 or into 6 fine positions. 052 * The odd numbers divide into 6 positions. In this kind a gral position is able to divide by 2, 3 and 6: 053 * <ul> 054 * <li>1: 1/6 = 0.1333 055 * <li>3: 1/3 = 0.3333 056 * <li>5: 1/2 = 0.5 057 * <li>7: 2/3 = 0.6667 058 * <li>9: 5/6 = 0.8667 059 * </ul> 060 * The even numbers divide into 5 positions: 061 * <ul> 062 * <li>2: 1/5 = 0.2 063 * <li>4: 2/5 = 0.4 064 * <li>6: 3/5 = 0.6 065 * <li>8: 4/5 = 0.8 066 * </ul> 067 * The fine positioning enables a fine positioning of widgets in respect to the fundamental positions. 068 * <br><br> 069 * <b>Positions as user arguments</b>:<br> 070 * Positions may be given with absolute values of grid units regarded to the actual panel or in related to the 071 * last or parent position. In that cases the constant values are added to the number, see the following list. 072 * The position is given in form 'from..to' for the line and column or in form 'from' and 'size'. 073 * The size may be given positive or negative. A positive size is counted from top or left to bottom or right. 074 * It means that the 'from' position is top or left. But a negative size is counted from right or bottom 075 * and the 'from' position is the right or bottom column and line. 076 * <br><br> 077 * <b>Position writing style in a gral script:</b><br> 078 * The appearance of a graphic can be given with a script using {@link org.vishia.gral.cfg.GralCfgZbnf}. 079 * The writing style of positions in the script regards a stinting short style to give positions, 080 * because a hand written script should not cause a lot of calculations for positions by the writer. 081 * It should be simple. The syntax of a position in the gral script is given in the variable {@link #syntaxZbnf}. 082 * The method {@link #setPosition(CharSequence, GralPos)} uses that syntax. 083 * <ul> 084 * <li>@myPanel, 5..7, 8..18: This is a full given absolute position. The element should be placed from line 5 to line 7 085 * and from column 8 to 18. The vertical position 7 is the bottom line, the column 18 is the right column exclusive. 086 * The horizontal size is 10, the vertical size is 2. 087 * <li>@myPanel, 5..7, 8..-1: This is a full given absolute position. The end column is given with a negative value. 088 * It means that the end column is related to the right border of the panel. 089 * <li>@myPanel, 5+2, 8+10: This is a full given position using the size. The element should be placed from line 5 090 * to line 7 and from column 8 to 18. The range is given as size. 091 * <li>@7-2, 18-10: The panel isn't given, so the panel of the last position, in the script in order of text, 092 * is used. The positions are exactly the same, from 5 to 7 and from 10 to 18. But because the size is given 093 * as negative value, the position value is the bottom line and the right column. A user may place elements 094 * with a common bottom line. The this form can be used. 095 * <li>@7-2, 10+18++1: This is the same position too. The '++' operator after size means, that the next element 096 * is positioning right side after the current in distance of 1 unit (distance feature TODO). 097 * <li>@-3,+4: The position isn't given yet. It means, the position of the last element is used. Because 098 * the size is negative, the bottom position of the last element is used. Because the last position is 099 * designated with '++' for column, the column value of position is the right value and the current element 100 * is placed right hand from the last one. This is an example of a button right from a text. The button is 101 * some times greater (3 units) in relation to the text (2 units), but they have the same button line. 102 * <li>@,+5: Here the line isn't specified. It is taken from the last position: bottom line 7 103 * and height 3. The column isn't given, it is taken form the last: Because the column position is cumulated, 104 * it is the 22 yet. 105 * <li>If no position is given, the position is the next position. In this example @7-3,27+5. 106 * <li>@,&2+10: The ampersand determines a relative position related to the last one. In this example 107 * the new column is 24 to 34. There is 2 units space. 108 * <li>@ $2-2,$+20: The dollar determines a relative position related to the last absolute given position. 109 * In this example it is line 7 and column 10. The new position is calculated with that values to line 9. 110 * The column 10 is the same column related to the last given absolute. 111 * This kind of specification allows determining some positions in lines and columns, 112 * whereby the absolute position is given only one time. (feature TODO) 113 * <li>@ %50-2,%10..%90: The positions are calculated from the size of the panel in percent. (feature TODO) 114 * </ul> 115 * <br><br> 116 * <b>Ranges and Designation of position parameter</b>: 117 * <ul> 118 * <li>Positive number in range 0...about 100..200 up to 1000: Grid Unit from left or top. 119 * <li>Negative number in range 0, -1...about -200..-200 up to 1000: Gral Unit from right or bottom. 120 * 0 for lineEnd or columnEnd means the right or bottom. 121 * <li>{@link #same} or {@link #refer} added with a number in range of -1000..1000: This given position 122 * refers to the parent position with the given distance. same and refer is equate, the difference 123 * is in semantic only. Use {@link #same} without distance, use {@link #refer} +/- distance. 124 * If {@link #same} or {@link #refer} is used for the line or column, and the second position is given 125 * with '{@link #size} - size' then the bottom or right value of the parent is referred. 126 * 127 * <li>{@link #size} + number applied at lineEnd or columnEnd: 128 * The size is given instead from..to. Because the size value is positive, the line and column value is left or top. 129 * <li>{@link #size} - number applied at lineEnd or columnEnd: The size is given negative. 130 * The absolute value is the size. Because the size is negative it is measured from right to left 131 * respectively bottom to top. It means the given line and column is the right or the bottom line. 132 * If the position is given using {@link #same} or {@link #refer}, the related end position 133 * is used. 134 * <li> {@link GralPos#next} and {@link GralPos#nextBlock} 135 * <li>as width or height or as percent value from the panel size. 136 * </ul> 137 * Fine positions are given always from left or top of the fundamental positions. 138 * For example a value -1.3 means, the widget is placed 1 unit from right, and then 1/3 inside this unit. 139 * This is 2/3 unit from right. A value for example -0.3 is not admissible, because -0 is not defined. 140 * <br><br> 141 * <b>The position values in this class</b>:<br> 142 * Though the position parameters may be given as size, with bottom line etc the position values are stored 143 * as absolute positions anyway. That are the elements {@link #x}, and {@link #y} with its values in 144 * {@link Coordinate}. 145 * The x and y is the lesser value, left and top, and the xEnd and yEnd is the greater value, right or bottom. 146 * This form of storing is better to calculate the pixel position while building the graphic and it is better 147 * to calculate related position too. 148 * <br><br> 149 * 150 * @author Hartmut Schorrig 151 * 152 */ 153public class GralPos implements Cloneable 154{ 155 /**Version, history and license. 156 * <ul> 157 * <li>2013-05-24 Hartmut bugfix fine position can be greater 20 if positions are add and sizes are add too. 158 * <li>2011-10-01 Hartmut corr: Calculation of next position or refer + value if the size was negative and sameSize is selected. 159 * Then the new input value should calculate from the bottom or left value because the size is negative furthermore. 160 * <li>2011-10-01 Hartmut bugfix: if(qf >= 10)... instead >10 161 * <li>2011-09-23 Hartmut chg: The methods {@link #setPosition(GralPos, float, float, float, float, int, char)} etc 162 * are moved from the GralGridMngBase to this. It are methods of this class functionally. The GralGridMngBase wrappes it 163 * because that methods should be able to call there. 164 * <li>2011-08-31 Hartmut new: constants {@link #same} etc. as adding values for setPosition-methods. 165 * It prevents the necessity of a lot of special set methods. The parameter for positions may be relative, referred etc. 166 * to the previous position or to a frame. 167 * <li>2011-08-31 Hartmut new: method {@link #toString()} to see values of instance in debug 168 * <li>2011-08-14 Hartmut new: creation of this class. Beforehand this values are stored inside the GralGridMngBase as main position. 169 * But a position in this kind is necessary in other contexts too, and the position values should be pooled in one class. 170 * </ul> 171 * <ul> 172 * <li>2011-06-00 Hartmut created 173 * </ul> 174 * 175 * <b>Copyright/Copyleft</b>:<br> 176 * For this source the LGPL Lesser General Public License, 177 * published by the Free Software Foundation is valid. 178 * It means: 179 * <ol> 180 * <li> You can use this source without any restriction for any desired purpose. 181 * <li> You can redistribute copies of this source to everybody. 182 * <li> Every user of this source, also the user of redistribute copies 183 * with or without payment, must accept this license for further using. 184 * <li> But the LPGL is not appropriate for a whole software product, 185 * if this source is only a part of them. It means, the user 186 * must publish this part of source, 187 * but doesn't need to publish the whole source of the own product. 188 * <li> You can study and modify (improve) this source 189 * for own using or for redistribution, but you have to license the 190 * modified sources likewise under this LGPL Lesser General Public License. 191 * You mustn't delete this Copyright/Copyleft inscription in this source file. 192 * </ol> 193 * If you intent to use this source without publishing its usage, you can get 194 * a second license subscribing a special contract with the author. 195 * 196 * @author Hartmut Schorrig = hartmut.schorrig@vishia.de 197 */ 198 public static final int version = 20120317; 199 200 201 /**This adding value applied at any coordinate parameter of any setPosition- method means, that the value is 202 * referred to the position of the previous or given position. The referred value may be given as positive or negative number. 203 * Adding this constant a value in range 0x7000...0x8000 to 0x8fff results for positions -4096...4095 (usual -100..100) 204 * Hint: If only the fractional part is changed, the non-fractional part should be given as refer. 205 */ 206 public final static int refer = 0x8000; 207 208 /**This value applied at any coordinate parameter of any setPosition- method means, that the value is 209 * the same as the previous or given position. 210 * Hint: The constant is equal to {@link #refer}. This constant regards the semantic. 211 */ 212 public final static int same = 0x8000; 213 214 /**Use the next value for the coordinate in relation to the last one for the given direction 215 * but the same value for the other coordinate. It is the typical value for both coordinates 216 * if a quasi-float layout is desired. 217 * This value can be applied to x, xEnd, y, yEnd or to the float given arguments of any setPosition- method. 218 * It uses xEnd for x and yEnd for y with the adequate fractional parts. 219 * The new value for xEnd or yEnd is calculated using the size if this value is applied to them. 220 */ 221 public final static int next = 0xdffe; 222 223 /**Use the next value for the coordinate in relation to the last one. 224 * This value can be applied to x, xEnd, y, yEnd or to the float given arguments of any setPosition- method. 225 * It uses xEnd for x and yEnd for y with the adequate fractional parts. 226 * The new value for xEnd or yEnd is calculated using the size if this value is applied to them. 227 */ 228 public final static int nextBlock = 0xdffd; 229 230 231 /**This value at xEnd or yEnd means, that the native size of a widget should be used. 232 * It is especially to draw images with its native size. 233 * This is a bit mask. The nature size is stored in the bits 12..0, that is maximal 8191 pixel 234 */ 235 public final static int useNatSize = 0xc000; 236 237 238 /**This bit at all coordinates means, that the value is given as ratio from the size. 239 * The bit {@link useNatSize} have to be 0. The ratio is stored as a value from 0 to 999 240 * in the bits 9..0. The other bits should be 0. 241 */ 242 public final static int ratio = 0xa000; 243 244 245 /**This adding value at xEnd or yEnd or the float presentations of the calling argument of any 246 * setPosition- method means, that the value is the size, not the position. 247 * A size can be positive or negative. A negative size determines, that the origin point for 248 * further elements or inner elements is on bottom line or right line of the current widget. 249 */ 250 public final static int size = 0x4000; //Note: Bit is contained in useNatSize, (pos = useNatSize | size) == useNatSize 251 252 253 /**Use the same size. 254 * 255 */ 256 public final static int samesize = 0x6000; 257 258 259 /**Bits in an integer position value for range and size. 260 * of relative position values for size, percent and refer. The mask for the value is 0x1fff. 261 * The range of any value is from 0x0 to 0x0fff for positive values and from 0x1fff downto 0x1000 262 * for negative values. The value == 0 is designated with 0x0 after mask. */ 263 private final static int mValueRange_ = 0x1fff, mValueNegative = 0x1000; 264 265 /**Bits in an integer position value for the type. 266 * If the type should be tested, the mTypwAdd_ should be added before masking. That is because 267 * the negative values for a specific type are disposed type - value */ 268 private final static int mType_ = 0xe000, kTypAdd_ = 0x1000; 269 270 /**Bit masks for the special types {@link #next}, {@link #nextBlock}, {@link #useNatSize}. */ 271 private final static int mSpecialType = 0xff00, kSpecialType=0xdf00; 272 273 /**Mask to check ratio. This bits should be mask and the ratio value should compare with them. */ 274 private final static int XXXmCheckRatio_ = 0xf000; 275 276 /**Mask for value of natural size. The maximum size is 16383 pixel. */ 277 private final static int XXXmNatSize_ = 0xf001; 278 279 /**Mask bits to designate related position, related end position and size. 280 * 281 */ 282 private final static int mBitRel = 0x1, mBitSize = 0x2, mBitRelEnd = 0x4, mBitSizeNeg = 8; 283 284 /**Position and mask of bits to designate kind of parameter. See {@link #parameterDesignation} */ 285 private final static int kBitParamDesignator_x = 0, kBitParamDesignator_y = 8, mParamDesignator = 0xff; 286 287 288 /**Syntax of a position. It is 289 * <pre> 290 position::= @ [<$?panel> ,] 291 [<?yPosRelative> &+] [<#?yPos>[\\.<#?yPosFrac>]] 292 [ [+] <#-?ySizeDown>[\\.<#?ySizeFrac>]| +* <?yOwnSize> |] 293 [ , [<?xPosRelative> &+] [<#?xPos>[\\.<#?xPosFrac>]] 294 [ [+] <#-?xWidth>[\\.<#?xSizeFrac>]| +* <?xOwnSize> |] [ <?xIncr> ++] 295 ]. 296 * </pre> 297 * The semantic identifier match to the elements in {@link org.vishia.gral.cfg.GralCfgPosition}. 298 * */ 299 public final static String syntaxZbnf = null; //not used because the syntax is evaluated by hard code. 300 /* 301 "position::= @ [<$?panel> ,]" 302 + " [<?yPosRelative> &+] [<#?yPos>[\\.<#?yPosFrac>]]" 303 + " [ [+] <#-?ySizeDown>[\\.<#?ySizeFrac>]| +* <?yOwnSize> |] ##| - <#?ySizeUp>|][ <?yIncr> ++]" 304 + " [ , [<?xPosRelative> &+] [<#?xPos>[\\.<#?xPosFrac>]]" 305 + " [ [+] <#-?xWidth>[\\.<#?xSizeFrac>]| +* <?xOwnSize> |] [ <?xIncr> ++]" 306 + " ] :"; 307 */ 308 309 310 311 /**The Property for the input parameter to use same, next etc. 312 * This value is used to generate an adequate config file from given input values. 313 * The coordinates don't carry the information about that input values. 314 */ 315 //public int parameterDesignation; 316 317 /**Position of any widget. 318 * Generally: There are coordinates in a grid, not in pixel. 319 * Positive value is from top or left, negative value is from right or bottom. 320 * {@link GralGridPos#useNatSize} on xEnd, yEnd means, that the natural size of the object should be used. 321 * 322 */ 323 //public int x, xEnd, y, yEnd; 324 325 326 327 /**Fractional part of position. 328 * Generally: It is a number from 0 to 9 as part of 1 grid unit. 329 */ 330 //public int xFrac, xEndFrac, yFrac, yEndFrac; 331 332 /**The values for x and y positions. Note: should be private! Don't use in application furthermore. */ 333 public final Coordinate x = new Coordinate(), y = new Coordinate(); 334 335 /**A GralPos should never create as instance from the application. It is created only from the GralMng which accesses package private. 336 * It is copied inside the GralMng for any widget. 337 * The position can be changed after them with {@link #setPosition(float, float)} etc. 338 */ 339 protected GralPos(){} 340 341 342 /**A GralPos should never create as instance from the application. It is created only from the GralMng which accesses package private. 343 * It is copied inside the GralMng for any widget. The position can be changed after them with {@link #setPosition(float, float)} etc. 344 * @param src the src position to copy all values. 345 */ 346 protected GralPos(GralPos src){ set(src); } 347 348 /**The border to the next element. */ 349 //public int xyBorder, xyBorderFrac; 350 351 /**Origin of widget, use l, m, r for xOrigin and t, m, b for yOrigin. */ 352 //public char xOrigin, yOrigin; 353 354 /**direction of the next element. Use r, d, l, u. */ 355 //public char dirNext; 356 357 /**Relation of x and y left and top to any separation line. 0 - relation to left and top border. */ 358 //public int xSepLine, ySepLine; 359 360 public GralPanelContent panel; 361 362 /**Sets all values of this with the values of pos (copy values) 363 * @param pos The src pos 364 */ 365 public void set(GralPos pos) 366 { x.attr = pos.x.attr; y.attr = pos.y.attr; 367 x.p1 = pos.x.p1; x.p2 = pos.x.p2; y.p1 = pos.y.p1; y.p2 = pos.y.p2; 368 x.p1Frac = pos.x.p1Frac; x.p2Frac = pos.x.p2Frac; y.p1Frac = pos.y.p1Frac; y.p2Frac = pos.y.p2Frac; 369 x.origin = pos.x.origin; y.origin = pos.y.origin; x.sepLine = pos.x.sepLine; y.sepLine = pos.y.sepLine; 370 x.dirNext = pos.x.dirNext; y.dirNext = pos.y.dirNext; 371 panel = pos.panel; 372 } 373 374 375 376 public void setPosition(float line, float column) 377 { 378 setPosition(this, line, size + same, column, size + same, 0, '.'); 379 } 380 381 382 383 384 /* (non-Javadoc) 385 * @see org.vishia.gral.gridPanel.GuiPanelMngBuildIfc#setPosition(int, int, int, int, char) 386 */ 387 public void setPositionSize(int line, int column, int height, int width, char direction, GralPos posFrame) 388 { setFinePosition(line, 0, height + GralPos.size, 0, column, 0, width + GralPos.size, 0, 1, direction, 0, 0, posFrame); 389 } 390 391 392 /**Sets the position with the given string representation. 393 * @param sPos The syntax of the string see description of this class, starting with "@panel, ..." etc. 394 * for example "@windowA, 3..5, 16+20" for absolute line 3 and 4 (exclusive 5) and from absolute column 16, size-x=20. 395 * The position can be given without panel designation or relative, then the posParent argument is necessary. 396 * @param posParent necessary to build the absolute position from relative given sPos, maybe null if not necessary. 397 * @throws ParseException on errors of sPos or missing posParent if necessary. 398 */ 399 public void setPosition(CharSequence sPos, GralPos posParent) throws ParseException { 400 GralPos posParent1; 401 //int line =0, yPosFrac =0, ye =0, yef =0, column =0, xPosFrac =0, xe =0, xef =0, origin =0, border =0, borderFrac =0; 402 Coordinate line = new Coordinate(), col = new Coordinate(); 403 int origin =0, border =0, borderFrac =0; 404 char direction = 'r'; 405 if(sPos ==null) { 406 //position text not given, use refer and same size 407 line.p1 = refer; 408 line.p2 = samesize; 409 //all other values of line and col remain 0. It is default. 410 col.p1 = refer; 411 col.p2 = samesize; 412 posParent1 = posParent; 413 } else { 414 //position given as text 415 StringPartScan spPos = new StringPartScan(sPos); 416 spPos.setIgnoreWhitespaces(true); 417 try { 418 spPos.scan("@").scanStart(); //skip over a first @ 419 if(spPos.scanIdentifier().scan(",").scanOk()) { //ckeck if a panel is given: 420 String sPanel = spPos.getLastScannedString().toString(); 421 GralMng mng = GralMng.get(); //singleton. 422 GralPanelContent panel = mng.getPanel(sPanel); 423 if(panel == null) { 424 spPos.close(); 425 throw new IllegalArgumentException("GralPos.setPosition - unknown panel, " + sPanel); 426 } 427 if(posParent !=null && panel == posParent.panel) { 428 posParent1 = posParent; 429 } else { 430 //only if it is another panel, remove the given parent. 431 posParent1 = new GralPos(); 432 } 433 } else { 434 posParent1 = posParent; //the parent is valid. Because no other panel. Use the current panel. 435 } 436 scanPosition(spPos, line); 437 if(spPos.scan(",").scanOk()) { 438 scanPosition(spPos, col); 439 } else { 440 col.p1 = refer; 441 col.p2 = samesize; 442 } 443 } finally { 444 spPos.close(); 445 } 446 } 447 setFinePosition(line.p1, line.p1Frac, line.p2, line.p2Frac, col.p1, col.p1Frac, col.p2, col.p2Frac, origin, direction, border, borderFrac, posParent1); 448 } 449 450 451 452 /**Scans one coordinate. 453 * <pre> 454 * [[<refer>+|-]<#?p1>[.<#p2Frac>] [..|<?size>]] <#?p2>[.<#p2Frac>] 455 * </pre> 456 * If only the right number is given, p1 is {@link #refer} 457 * @param spPos 458 * @param co 459 * @throws ParseException 460 */ 461 private void scanPosition(StringPartScan spPos, Coordinate co) throws ParseException { 462 char sign = spPos.seekNoWhitespace().getCurrentChar(); 463 int size1; //maybe size for end element, converted to refer for start element. 464 co.p1 = next; //default, next line or next column depending on parent. 465 co.p1Frac = 0; 466 co.p2 = samesize; 467 co.p2Frac = 0; 468 // 469 if("+-".indexOf(sign) >=0){ 470 size1 = size; 471 spPos.seek(1); //skip + or - 472 } else if(sign == '%'){ 473 size1 = ratio; 474 spPos.seek(1); //skip + or - 475 } else { 476 size1 = 0; 477 } 478 if(spPos.scanInteger().scanOk()) { 479 int pos1 = (int)spPos.getLastScannedIntegerNumber(); 480 if(sign == '-'){ pos1 = -pos1; } 481 co.p2 = size1 + pos1; 482 if(spPos.scan(".").scanInteger().scanOk()) { 483 co.p2Frac = (int)(spPos.getLastScannedIntegerNumber() % 10); //should be 0..9 484 } 485 } 486 int size2; 487 if(spPos.scan("..").scanOk()) { //position for end is given 488 size2 = 0; 489 } else { 490 size2 = size; 491 spPos.scan("+").scanStart(); //skip over '+', it is the separator, 492 } 493 if(spPos.scanInteger().scanOk()) { //can start with '-' but not with '+' 494 //between 2. number is given, first is p1 495 if(size1 == size){ 496 co.p1 = co.p2 - size; //stored as size for end element, but it is negative for first element. 497 } else { 498 co.p1 = co.p2; //ratio or absolute 499 } 500 co.p1Frac = co.p2Frac; 501 // 502 co.p2Frac = 0; //default 503 co.p2 = size2 + (int)spPos.getLastScannedIntegerNumber(); //positive or negative. Negative means from left or bottom. 504 if(spPos.scan(".").scanInteger().scanOk()) { 505 co.p2Frac = (int)(spPos.getLastScannedIntegerNumber() % 10); //should be 0..9 506 } 507 } 508 509 } 510 511 512 513 /**Sets the position to the given panel as container. 514 * @param panel The panel which is used as container. Its current {@link GralPanelContent#pos()} is used for relative positions 515 * @param line The line. If the parameter lineEndOrSize is designated with {@link #size} with a negative value, 516 * it is the bottom line for the position. 517 * If it is designated with {@link #same} without offset and the lineEndOrSize is designated with {@link #size} 518 * with a negative value, the framePos {@link GralPos#y.p2} is used. If it is designated 519 * with {@link #same} but with any offset, the {@link GralPos#y} is used as refer position, it is the top line position. 520 * Elsewhere it is the top position. 521 * 522 * @param lineEndOrSize Maybe designated with {@link #size} or {@link #samesize} 523 * @param column 524 * @param columnEndOrSize 525 * @param origin 526 * @param direction 527 */ 528 public void setPosition(GralPanelContent panel, float line, float lineEndOrSize, float column, float columnEndOrSize 529 , int origin, char direction, float border) 530 { 531 this.panel = panel; 532 int[] pos = new int[10]; 533 frac(line, pos, 0); 534 frac(lineEndOrSize, pos, 2); 535 frac(column, pos, 4); 536 frac(columnEndOrSize, pos, 6); 537 frac(border, pos, 8); 538 setFinePosition(pos[0], pos[1], pos[2], pos[3], pos[4], pos[5], pos[6], pos[7], origin, direction, pos[8], pos[9], panel.pos()); 539 /* 540 int y1 = (int)(line); 541 int y1f = frac(y1, line); 542 int y2 = (int)(lineEndOrSize); 543 int y2f = frac(y2, lineEndOrSize); 544 int x1 = (int)(column); 545 int x1f = frac(x1, column); 546 int x2 = (int)(columnEndOrSize); 547 int x2f = frac(x2, columnEndOrSize); 548 setFinePosition(y1, y1f, y2, y2f, x1, x1f, x2, x2f, origin, direction, framePos); 549 */ 550 } 551 552 553 554 555 /**Sets the position 556 * @param framePos The frame or last pos for relative positions. 557 * @param line The line. If the parameter lineEndOrSize is designated with {@link #size} with a negative value, 558 * it is the bottom line for the position. 559 * If it is designated with {@link #same} without offset and the lineEndOrSize is designated with {@link #size} 560 * with a negative value, the framePos {@link GralPos#y.p2} is used. If it is designated 561 * with {@link #same} but with any offset, the {@link GralPos#y} is used as refer position, it is the top line position. 562 * Elsewhere it is the top position. 563 * 564 * @param lineEndOrSize Maybe designated with {@link #size} or {@link #samesize} 565 * @param column 566 * @param columnEndOrSize 567 * @param origin 568 * @param direction 569 */ 570 public void setPosition(GralPos framePos, float line, float lineEndOrSize, float column, float columnEndOrSize 571 , int origin, char direction, float border) 572 { 573 int[] pos = new int[10]; 574 frac(line, pos, 0); 575 frac(lineEndOrSize, pos, 2); 576 frac(column, pos, 4); 577 frac(columnEndOrSize, pos, 6); 578 frac(border, pos, 8); 579 setFinePosition(pos[0], pos[1], pos[2], pos[3], pos[4], pos[5], pos[6], pos[7], origin, direction, pos[8], pos[9], framePos); 580 /* 581 int y1 = (int)(line); 582 int y1f = frac(y1, line); 583 int y2 = (int)(lineEndOrSize); 584 int y2f = frac(y2, lineEndOrSize); 585 int x1 = (int)(column); 586 int x1f = frac(x1, column); 587 int x2 = (int)(columnEndOrSize); 588 int x2f = frac(x2, columnEndOrSize); 589 setFinePosition(y1, y1f, y2, y2f, x1, x1f, x2, x2f, origin, direction, framePos); 590 */ 591 } 592 593 594 /**Returns true if this position is from right or bottom, so that a resize of the panel needs new positions for this widget. 595 */ 596 public boolean toResize(){ return x.p1 < 0 || x.p2 <= 0 || y.p1< 0 || y.p2 <=0; } 597 598 private void frac(float v, int[] pos, int ix){ 599 int i, f; 600 i = (int)v; 601 if((i & mValueNegative) !=0){ 602 f = (int)((v-i)*10 + 0.5f); 603 if( f == 10){ f = 0; } 604 } else { 605 f = (int)((v - i)*10 + 0.5f); 606 } 607 if(f < 0){ 608 i -=1; f +=10; 609 } 610 assert(f >=0 && f <= 9); 611 pos[ix] = i; pos[ix+1]= f; 612 //return f; 613 } 614 615 616 617 618 619 public void setPosition(GralPos framePos, float line, float lineEndOrSize, float column, float columnEndOrSize 620 , int origin, char direction) 621 { 622 setPosition(framePos, line, lineEndOrSize, column, columnEndOrSize, origin, direction, 0); 623 } 624 625 626 /**Sets the position for the next widget to add in the container. 627 * Implementation note: This is the core function to calculate positions. It is called from all other ones. 628 * @param line y-Position in y-Units, count from top of the box. It is the bottom line of the widget. 629 * If <0, then it counts from bottom of the parent. 630 * @param column x-Position in x-Units, count from left of the box. 631 * If <0, then the previous position is valid still. 632 * It < 0 then line = 0 is not a proper value. To show a text in the first line, use line=2. 633 * @param heigth: The height of the line. If <0, then the param line is the bottom line of the widget, 634 * and (line-height) is the top line. If 0 then the last value of height is not changed. 635 * @param length: The number of columns. If <0, then the param column is the right column, 636 * and column-length is the left column. If 0 then the last value of length is not changed. 637 * @param direction: direction for a next widget, use 'r', 'l', 'u', 'd' for right, left, up, down 638 * @param parent 639 */ 640 public void setFinePosition(int line, int yPosFrac, int ye, int yef 641 , int column, int xPosFrac, int xe, int xef, int origin, char direction 642 , int border, int borderFrac 643 , GralPos parent) 644 { 645 // 646 if(yPosFrac < 0 || yPosFrac >9){ 647 throw new IllegalArgumentExceptionJc("GralPos - yPosFrac error", yPosFrac); 648 } 649 if(xPosFrac < 0 || xPosFrac >9) { 650 throw new IllegalArgumentExceptionJc("GralPos - xPosFrac error", xPosFrac); 651 } 652 // 653 if(ye == (size -1) && yef == 5) 654 stop(); 655 if(ye == useNatSize) 656 stop(); 657 // 658 if(parent == null){ parent = this; } 659 if(origin >0 && origin <=9){ 660 int yOrigin = (origin-1) /3; 661 int xOrigin = origin - yOrigin -1; //0..2 662 this.x.origin = "lmr".charAt(xOrigin); 663 this.y.origin = "tmb".charAt(yOrigin); 664 } 665 666 y.set(line, yPosFrac, ye, yef, parent.y); 667 x.set(column, xPosFrac, xe, xef, parent.x); 668 669 if("rl".indexOf(direction)>=0 ){ 670 this.x.dirNext = direction; 671 this.y.dirNext = '.'; 672 this.x.pb = border; 673 this.x.pbf = borderFrac; 674 this.y.pb = this.y.pbf = 0; 675 } else if("ud".indexOf(direction)>=0 ){ 676 this.y.dirNext = direction; 677 this.x.dirNext = '.'; 678 this.y.pb = border; 679 this.y.pbf = borderFrac; 680 this.x.pb = this.x.pbf = 0; 681 } else { 682 this.x.dirNext = parent.x.dirNext; 683 this.y.dirNext = parent.y.dirNext; 684 this.x.pb = parent.x.pb; this.x.pbf = parent.x.pbf; 685 this.y.pb = parent.y.pb; this.y.pbf = parent.y.pbf; 686 } 687 assert(x.p1Frac >=0 && x.p1Frac < 10 && y.p1Frac >=0 && y.p1Frac < 10 ); 688 assert(x.p2Frac >=0 && x.p2Frac < 10 && y.p2Frac >=0 && y.p2Frac < 10 ); 689 } 690 691 692 693 694 public void setSize(int height, int ySizeFrac, int width, int xSizeFrac) 695 { 696 if(height !=0){ 697 //ySize = height >0 ? height : -height; 698 //this.ySizeFrac = ySizeFrac; 699 } 700 if(width !=0){ 701 //xSize = width >0 ? width: -width; 702 //this.xSizeFrac = xSizeFrac; 703 } 704 if(height >0){ this.y.origin = 't'; } 705 else if(height < 0){ this.y.origin = 'b'; } 706 else; //let it unchanged if height == 0 707 if(width >0){ this.x.origin = 'l'; } 708 else if(width < 0){ this.x.origin = 'r'; } 709 else; //let it unchanged if width == 0 710 } 711 712 713 public void setSize(float height, float width, GralPos frame) 714 { 715 int y2 = (int)(height); 716 int y2f = y2 >=0 ? (int)((height - y2)* 10.001F) : (int)((height - y2)* -10.001F); 717 int x2 = (int)(width); 718 int x2f = x2 >=0 ? (int)((width - x2)* 10.001F) : (int)((width - x2)* -10.001F); 719 setFinePosition(GralPos.next, 0, y2 + GralPos.size, y2f, GralPos.next, 0, x2 + GralPos.size, x2f, 0, '.', 0, 0, frame); 720 } 721 722 723 /**Sets the position to the next adequate the {@link #pos.dirNext}. */ 724 public void setNextPosition() 725 { 726 setPosition(this, next, samesize, next, samesize, 0, '.', 0 ); 727 /* 728 float dx3 = this.width(); 729 float dy3 = this.height(); 730 int dx = (int)dx3; 731 int dxf = (int)((dx3 - dx) * 10.001F) + this.x.p2Frac; 732 if(dxf >= 10){ dxf -=10; dx +=1; } 733 int dy = (int)dy3; 734 int dyf = (int)((dy3 - dy) * 10.001F) + this.y.p2Frac; 735 if(dyf >= 10){ dyf -=10; dy +=1; } 736 switch(this.dirNext){ 737 case 'r': this.x = this.x.p2; this.x.p1Frac = this.x.p2Frac; this.x.p2 = this.x + dx; this.x.p2Frac = dxf; break; 738 case 'd': this.y = this.y.p2; this.y.p1Frac = this.y.p2Frac; this.y.p2 = this.y + dy; this.y.p2Frac = dyf; break; 739 } 740 */ 741 } 742 743 744 745 746 747 748 749 public float height() 750 { float height; 751 if(y.p1 * y.p2 >= 0){ 752 height = y.p2 - y.p1; 753 if((y.attr & mBitSizeNeg)!=0) { 754 height = -height; 755 } 756 } 757 else{ 758 height = 2.0F; //not able to determine, use default. 759 } 760 height += (y.p2Frac - y.p1Frac) * 0.1F; 761 return height; 762 } 763 764 765 public float width() 766 { float width; 767 if(y.p1 > 0 && x.p2 > 0){ width = x.p2 - y.p1 + (x.p2Frac - x.p1Frac) * 0.1F; } 768 else if(x.p1 < 0 && x.p2 < 0){ width = x.p2 - x.p1 + (x.p2Frac - x.p1Frac) * 0.1F; } 769 else { width = 0.0F; } //not able to determine, use default. 770 return width; 771 } 772 773 774 775 776 777 778 @Override public GralPos clone(){ 779 //Hint: Object.clone() can't be used because it clones the references of x and y and not its values. 780 GralPos newObj = new GralPos(); 781 newObj.x.set(x); 782 newObj.y.set(y); 783 newObj.panel = panel; 784 //try{ newObj = (GralGridPos)super.clone(); 785 //} catch(CloneNotSupportedException exc){ assert(false); } 786 return newObj; 787 } 788 789 790 791 792 public GralPos setNextPos(String posString) throws ParseException { 793 if(posString.equals("!")) { //new window, initialize the position without panel because it is top. 794 panel = null; 795 setFinePosition(0,0,0,0,0,0,0,0,0,'d', 0,0, null); 796 } else { 797 setPosition(posString, this); 798 //TODO change pos: 799 } 800 return clone(); //return the pos as clone, to use as posWidg 801 } 802 803 804 805 806 807 808 809 810 /**Calculates the position and size of a widget from this given Pos. 811 * @param propertiesGui The properties for presentation. 812 * @param widthParentPixel width of the container. This value will be used if the position is given 813 * from right with negative numbers. 814 * @param heightParentPixel height of the container. This value will be used if the position is given 815 * from bottom with negative numbers. 816 * @param widthWidgetNat natural width of the component which will be positioning. 817 * This value is used only if the pos parameter contains {@link GralPos#useNatSize} for the xe-value 818 * @param heightWidgetNat natural height of the component which will be positioning. 819 * This value is used only if the pos parameter contains {@link GralPos#useNatSize} for the ye-value 820 * @return A rectangle for setBounds. 821 */ 822 public GralRectangle calcWidgetPosAndSize(GralGridProperties propertiesGui, 823 int widthParentPixel, int heightParentPixel, 824 int widthWidgetNat, int heightWidgetNat 825 ) 826 { 827 int xPixelUnit = propertiesGui.xPixelUnit(); 828 int yPixelUnit = propertiesGui.yPixelUnit(); 829 //calculate pixel 830 final int x1,y1, x2, y2; 831 /// 832 833 x1 = xPixelUnit * this.x.p1 + propertiesGui.xPixelFrac(this.x.p1Frac) //negative if from right 834 + (this.x.p1 < 0 ? widthParentPixel : 0); //from right 835 y1 = yPixelUnit * this.y.p1 + propertiesGui.yPixelFrac(this.y.p1Frac) //negative if from right 836 + (this.y.p1 < 0 ? heightParentPixel : 0); //from right 837 if(this.x.p2 == GralPos.useNatSize){ 838 x2 = x1 + widthWidgetNat; 839 } else { 840 x2 = xPixelUnit * this.x.p2 + propertiesGui.xPixelFrac(this.x.p2Frac) //negative if from right 841 + (this.x.p2 < 0 || this.x.p2 == 0 && this.x.p2Frac == 0 ? widthParentPixel : 0); //from right 842 } 843 if(this.x.p2 == GralPos.useNatSize){ 844 y2 = y1 + heightWidgetNat; 845 } else { 846 y2 = yPixelUnit * this.y.p2 + propertiesGui.yPixelFrac(this.y.p2Frac) //negative if from right 847 + (this.y.p2 < 0 || this.y.p2 == 0 && this.y.p2Frac == 0 ? heightParentPixel : 0); //from right 848 } 849 GralRectangle rectangle = new GralRectangle(x1, y1, x2-x1-1, y2-y1-1); 850 return rectangle; 851 } 852 853 854 855 856 private static void appendPos(StringBuilder b, int p, int pFrac) 857 { 858 if(pFrac >0) { 859 if(p < 0) { b.append(p-1); } else { b.append(p); } 860 b.append('.').append(pFrac); 861 } else { 862 b.append(p); 863 } 864 } 865 866 867 868 869 public String posString() 870 { StringBuilder b = new StringBuilder(16); 871 b.append('@'); 872 if(panel != null) { 873 b.append(panel.name).append(", "); 874 } 875 appendPos(b, y.p1, y.p1Frac); 876 b.append(".."); 877 appendPos(b, y.p2, y.p2Frac); 878 b.append(","); 879 appendPos(b, x.p1, x.p1Frac); 880 b.append(".."); 881 appendPos(b, x.p2, x.p2Frac); 882 return b.toString(); 883 } 884 885 /**Use especially for debug. 886 * @see java.lang.Object#toString() 887 */ 888 @Override public String toString() 889 { return "panel=" + (panel == null ? "?" : panel.toString()) + ", " 890 +"line=" + y.p1 + "." + y.p1Frac + ".." + y.p2 + "." + y.p2Frac + " col=" + x.p1 + "." + x.p1Frac + ".." + x.p2 + "." + x.p2Frac + " " + x.dirNext + y.dirNext + y.origin + x.origin; 891 } 892 893 894 895 void stop(){} 896 897 898 /**Class holds values for either x or y. Both values are calculated with adequate algorithms, 899 * so that algorithm is written only one time but called 2 times for x and for y. 900 * 901 * 902 */ 903 public static class Coordinate 904 { 905 /**The start position for the spread. 906 * If there are positive numbers, they count from left to right respectively top to bottom. 907 * If the value is negative, the absolute is the distance from right respectively bottom. 908 */ 909 public int p1; 910 911 /**The end position for the spread. 912 * If there are positive numbers, they count from left to right respectively top to bottom. 913 * If the value is negative or 0, the absolute is the distance from right respectively bottom. 914 */ 915 public int p2; 916 917 /**Start Position in percent. If -1 then not used. 918 * 919 */ 920 int n1 = -1; 921 /// 922 /**End Position in percent. */ 923 int n2; 924 925 /**Fractional parts of position. Use 0..9 only. 926 * The fractional part counts from left to right respectively top to bottom 927 * independent of the sign of p1, p2. 928 */ 929 public int p1Frac, p2Frac; 930 931 /**Additional border value for {@link GralPos#next}. */ 932 public int pb, pbf; 933 934 /**Attributes of this coordinate. */ 935 public int attr; 936 937 char origin; 938 939 /**direction of the next element. Use r, d, l, u. */ 940 public char dirNext; 941 942 943 /**Relation of x and y left and top to any separation line. 0 - relation to left and top border. 944 * TODO the sepLine is planned but not used yet. 2012-01-31 */ 945 public int sepLine; 946 /**Relation of xEnd and yEnd right and bottom to any separation line. 947 * 0 - relation to left and top border. 948 * positive Index: separation line with this index is left or top. Typical it may be the same index 949 * then for left top position. 950 * negative Index: separation line with negate value as index is right or bottom. */ 951 public int endSepLine; 952 953 /**Sets the new position for this coordinate. 954 * @param z1 955 * @param z1Frac 956 * @param z2 957 * @param z2Frac 958 * @param parent The refer position. Note that parent may be == this because the new position based on the current. 959 */ 960 public Coordinate set(final int z1, final int z1Frac, final int z2, final int z2Frac, final Coordinate parent) 961 { 962 /**User final local variable to set p, pf, pe, pef to check whether all variants are regarded. */ 963 final int q1, q1Frac, q2, q2Frac; 964 965 //check input parameter ze of size and negative size 966 967 //The type of input parameter. 968 final boolean zNeg = (z1 & mValueNegative) !=0; 969 final int zType = (z1 & mSpecialType) == kSpecialType ? z1 : (z1 + kTypAdd_) & mType_; 970 final boolean zeNeg = (z2 & mValueNegative) !=0; 971 final int zeType = (z2 & mSpecialType) == kSpecialType ? z2 : (z2 + kTypAdd_) & mType_; 972 final int testCase; 973 final int testType = (zType<<16) + zeType; 974 if(parent !=this){ 975 pb = parent.pb; pbf = parent.pbf; 976 } 977 switch(testType){ 978 // 979 case 0: { 980 testCase = 1; 981 q1 = z1; q1Frac = z1Frac; //q = z 982 q2 = z2; q2Frac = z2Frac; //qe = ze 983 } break; 984 // 985 case 0 + refer: { 986 testCase = 2; //q = z 987 q1 = z1; q1Frac = z1Frac; //qe = pe + refer 988 q2 = parent.p2 + (z2 - refer); q2Frac = parent.p2Frac + z2Frac; 989 } break; 990 // 991 case 0 + size: { 992 testCase = 3; 993 if(zeNeg){ 994 q2 = z1; q2Frac = z1Frac; //qe = z 995 q1 = q2 + (z2 - size); q1Frac = q2Frac + z2Frac; //q = qe + size 996 } else { 997 q1 = z1; q1Frac = z1Frac; //q = z 998 q2 = q1 + (z2 - size); q2Frac = q1Frac +z2Frac; //qe = q + size 999 } 1000 } break; 1001 // 1002 case 0 + samesize: { 1003 testCase = 4; 1004 if( (attr & mBitSizeNeg) !=0){ //was the last size negative? the qe is base 1005 q2 = z1; q2Frac = z1Frac; //qe = z 1006 q1 = q2 - (parent.p2 - parent.p1) + (z2 - samesize); //q = qe - lastsize + sizediff 1007 q1Frac = q2Frac + (parent.p2Frac - parent.p1Frac) + z2Frac; 1008 } else { 1009 q1 = z1; q1Frac = z1Frac; //q = z 1010 q2 = q1 + (parent.p2 - parent.p1) + (z2 - samesize); //qe = q + lastsize + sizediff 1011 q2Frac = q1Frac + (parent.p2Frac - parent.p1Frac) + z2Frac; 1012 } 1013 } break; 1014 // 1015 case 0 + useNatSize: { 1016 testCase = 11; 1017 q1 = z1; q1Frac = z1Frac; 1018 q2 = z2; q2Frac = 0; //store useNatSize 1019 } break; 1020 // 1021 case (refer<<16) + 0: { 1022 testCase = 5; 1023 q1 = parent.p1 + (z1 - refer); q1Frac = parent.p1Frac + z1Frac; //q = p + refer 1024 q2 = z2; q2Frac = z2Frac; //qe = ze 1025 } break; 1026 // 1027 case (refer<<16) + refer: { 1028 testCase = 1; 1029 q1 = parent.p1 + (z1 - refer); q1Frac = parent.p1Frac + z1Frac; //q = parent.p + refer 1030 q2 = parent.p2 + (z2 - refer); q2Frac = parent.p2Frac + z2Frac; //qe = parent.pe + refer 1031 } break; 1032 // 1033 case (refer<<16) + size: { 1034 testCase = 6; 1035 if(zeNeg){ 1036 q2 = parent.p2 + (z1 - refer); q2Frac = parent.p2Frac + z1Frac; //qe = parent.pe + refer, z is the bottom/right pos 1037 q1 = q2 + (z2 - size); q1Frac = q2Frac + z2Frac; //q = qe - size 1038 } else { 1039 q1 = parent.p1 + z1 - refer; q1Frac = parent.p1Frac + z1Frac; //q = parent.p + refer 1040 q2 = q1 + (z2 - size); q2Frac = q1Frac + z2Frac; //qe = q + size 1041 } 1042 } break; 1043 // 1044 case (refer<<16) + samesize: { 1045 testCase = 7; 1046 if( (attr & mBitSizeNeg) !=0){ 1047 q1 = z1 - (parent.p2 - parent.p1) + z2 - samesize; q1Frac = z1Frac - (parent.p2Frac - parent.p1Frac); 1048 q2 = parent.p2 + z1 - refer; q2Frac = z2Frac; 1049 } else { 1050 q1 = parent.p1 + (z1 - refer); q1Frac = parent.p1Frac + z1Frac; //q = parent.p + refer 1051 q2 = q1 + (parent.p2 - parent.p1) + (z2 - samesize); //qe = q + lastsize + sizediff 1052 q2Frac = q1Frac + (parent.p2Frac - parent.p1Frac) + z2Frac; 1053 } 1054 } break; 1055 // 1056 case (next<<16) + refer: { 1057 testCase = 8; 1058 q1 = parent.p2 + parent.pb; q1Frac = parent.p2Frac + parent.pbf; //q = parent.pe + parent.pb the next right/down 1059 q2 = q1 + (parent.p2 - parent.p1) + (z2 - refer); q2Frac = q1Frac + (parent.p2Frac - parent.p1Frac) + z2Frac; //qe = q + (parent.pe - parent.p) + refer 1060 } break; 1061 // 1062 case (next<<16) + size: { 1063 testCase = 10; 1064 //switch(dirNext){ 1065 switch(parent.dirNext){ 1066 case 'r': case 'd': { 1067 if( (attr & mBitSizeNeg) !=0){ 1068 q2 = parent.p2 + parent.pb; q2Frac = parent.p2Frac + parent.pbf; 1069 q1 = q2 - (parent.p2 - parent.p1) + (z2 - size); q1Frac = q2Frac - (parent.p2Frac - parent.p1Frac) + z2Frac; 1070 } else { //same as next, refer 1071 q1 = parent.p2 + parent.pb; q1Frac = parent.p2Frac + parent.pbf; //q = parent.pe + parent.pb the next right/down 1072 q2 = q1 + z2 - size; q2Frac = q1Frac + z2Frac; 1073 } 1074 } break; 1075 // 1076 default: { 1077 q1 = parent.p1; q1Frac = parent.p1Frac; q2 = parent.p2; q2Frac = parent.p2Frac; //don't change this coordinate. It may be the other one. 1078 } 1079 } 1080 } break; 1081 // 1082 case (next<<16) + samesize: { //z1 is next, ze is samesize, means typical next 1083 testCase = 9; 1084 switch(parent.dirNext){ 1085 case 'r': case 'd': { 1086 if( (attr & mBitSizeNeg) !=0){ 1087 q2 = parent.p2 + (parent.p2 - parent.p1) + parent.pb; q2Frac = parent.p2Frac + (parent.p2Frac - parent.p1Frac) + parent.pbf; 1088 q1 = q2 - (parent.p2 - parent.p1) + (z2 - samesize); q1Frac = q2Frac - (parent.p2Frac - parent.p1Frac) + z2Frac; 1089 } else { //same as next, refer 1090 q1 = parent.p2 + parent.pb; q1Frac = parent.p2Frac + parent.pbf; //q = parent.pe + parent.pb the next right/down 1091 q2 = q1 + (parent.p2 - parent.p1) + z2 - samesize; q2Frac = q1Frac + (parent.p2Frac - parent.p1Frac) + z2Frac; 1092 } 1093 } break; 1094 // 1095 default: { 1096 q1 = parent.p1; q1Frac = parent.p1Frac; q2 = parent.p2; q2Frac = parent.p2Frac; //don't change this coordinate. It may be the other one. 1097 } 1098 } 1099 } break; 1100 default: 1101 assert(false); 1102 testCase = 12; 1103 q1 = z1; q1Frac = z1Frac; 1104 q2 = z2; q2Frac = z2Frac; 1105 } 1106 1107 if(!(q1 <= q2 || q2 <=0)){ 1108 throw new IllegalArgumentException("start > end " + q1 + " > " + q2); 1109 } 1110 if(!(q1 > -1000 && q1 < 1000 && ((q2 > -1000 && q2 < 1000) || ((q2 - useNatSize) >=0 && (q2 - useNatSize) < 8192)))){ 1111 throw new IllegalArgumentException("positions out of range" + q1 + ", " + q2); 1112 } 1113 if(q1Frac >= 20){ //can be on adding distance 1114 this.p1 = q1 +2; this.p1Frac = q1Frac -20; 1115 } else if(q1Frac >= 10){ 1116 this.p1 = q1 +1; this.p1Frac = q1Frac -10; 1117 } else if(q1Frac < 0){ 1118 this.p1 = q1 - 1; this.p1Frac = q1Frac +10; 1119 } else { 1120 this.p1 = q1; this.p1Frac = q1Frac; 1121 } 1122 if(q2Frac >= 20){ 1123 this.p2 = q2 +2; this.p2Frac = q2Frac -20; 1124 } else if(q2Frac >= 10){ 1125 this.p2 = q2 +1; this.p2Frac = q2Frac -10; 1126 } else if(q2Frac < 0){ 1127 this.p2 = q2 - 1; this.p2Frac = q2Frac +10; 1128 } else { 1129 this.p2 = q2; this.p2Frac = q2Frac; 1130 } 1131 if(!(p1Frac >=0 && p1Frac <=9 && p2Frac >=0 && p2Frac <=9 )){ 1132 throw new IllegalArgumentException("Fractional position failure: " + p1Frac + ", " + p2Frac); 1133 } 1134 return this; 1135 }//set 1136 1137 1138 /**Copies all values. Hint: clone isn't able to use because the instance in parent is final. 1139 * @param src 1140 */ 1141 void set(Coordinate src){ 1142 p1 = src.p1; p1Frac = src.p1Frac; p2 = src.p2; p2Frac = src.p2Frac; 1143 pb = src.pb; pbf = src.pbf; attr = src.attr; origin = src.origin; dirNext = src.dirNext; 1144 sepLine = src.sepLine; endSepLine = src.endSepLine; 1145 } 1146 1147 1148 /// 1149 /**Calculate from size to pixel. 1150 * 1151 */ 1152 void calc(int[] dst, int dparent, int dnat, int xPixelUnit, int[] xPixelFrac){ 1153 int x1, x2; //begin, end 1154 int min, max; 1155 1156 //maximum of width 1157 x1 = xPixelUnit * p1 + xPixelFrac[p1Frac] //negative if from right 1158 + (p1 < 0 ? dparent : 0); //from right 1159 if(p2 == GralPos.useNatSize){ 1160 x2 = x1 + dnat; 1161 } else { 1162 x2 = xPixelUnit * p2 + xPixelFrac[p2Frac] //negative if from right 1163 + (p2 < 0 || p2 == 0 && p2Frac == 0 ? dparent : 0); //from right 1164 } 1165 1166 1167 if(n1 >=0 && ((1000 * (x2 - x1))/dparent) > (n2 - n1) ){ 1168 //The percent size is less then the maximum size, use it. 1169 x1 = n1 * dparent; 1170 x2 = n2 * dparent; 1171 max = xPixelUnit * p2; 1172 min = xPixelUnit * p1; 1173 } 1174 } 1175 1176 } 1177 1178 1179 public static void testScanSize(){ 1180 GralPos posParent = new GralPos(); 1181 GralPos posTest = new GralPos(); 1182 try{ 1183 posParent.setPosition("@3+2, 10+10", null); //line 3, column 10 + 10 1184 posTest.setPosition(",+12", posParent); //line 3, column 20 + 12 1185 Assert.checkMsg(posParent.y.p1 == 3 && posParent.y.p2 == 5 && posParent.x.p1 == 10 && posParent.x.p2 == 20 , "posParent failure"); 1186 Assert.checkMsg(posTest.y.p1 == 3 && posTest.y.p2 == 5 && posTest.x.p1 == 20 && posTest.x.p2 == 32 , "posTest failure"); //next, size=12 1187 } catch(ParseException exc) { 1188 System.err.println("GralPos.testScanSize - error, " + exc.getMessage()); 1189 } 1190 1191 } 1192}