Changeset 1095


Ignore:
Timestamp:
01/30/18 11:51:48 (6 years ago)
Author:
bln4
Message:

Fixed getPixelBoundsUnion()

  • Unfortunately, text layout objects relating to Text Item lines gave the (x,y) position of the entire Text Item, not that line specifically. In other words getPixelBounds(_textLayouts.get(0)).x == getPixelBounds(_textLayouts.get(1)).x. This meant that multiline Text Items were not producing the correct bounding box. A reimplementation has fixed this.

Added getPixelBoundsUnionTight()

  • Unlike getPixelBoundsUnion() that returns 'gravity-less' rectangle, getPixelBoundsUnionTight() returns a 'gravity-less' polygon. The outline of the polygon follows the length of individual lines in the Text Item.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/expeditee/items/Text.java

    r1047 r1095  
    129129
    130130        /*
    131          * Set the width to be IMPLICIT, but as wide as possible, a negative width
    132          * value is one that is implicitly set by the system... a positive value is
    133          * one explicitly set by the user.
     131         * Set the width to be IMPLICIT, but as wide as possible, a negative width value
     132         * is one that is implicitly set by the system... a positive value is one
     133         * explicitly set by the user.
    134134         */
    135135        private Integer _maxWidth = Integer.MIN_VALUE + 1;
     
    149149
    150150        private int _selectionEnd = -1;
    151        
     151
    152152        // whether autowrap is on/off for this item
    153153        protected boolean _autoWrap = false;
     
    165165        // The font to display this text in
    166166        private Font _font;
    167        
    168        
    169         protected static void InitFontFamily(GraphicsEnvironment ge, File fontFamilyDir)
    170         {
     167
     168        protected static void InitFontFamily(GraphicsEnvironment ge, File fontFamilyDir) {
    171169                File[] fontFiles = fontFamilyDir.listFiles();
    172170
     
    179177
    180178                        if (i > p) {
    181                                 ext = fileName.substring(i+1);
     179                                ext = fileName.substring(i + 1);
    182180                        }
    183181
     
    187185                                        Font font = Font.createFont(Font.TRUETYPE_FONT, fontFile);
    188186
    189                                         boolean registered_status_ok= ge.registerFont(font);
     187                                        boolean registered_status_ok = ge.registerFont(font);
    190188
    191189                                        if (registered_status_ok) {
    192                                            
    193                                             String font_family = font.getFamily();
    194                                             if (!FONT_WHEEL_ADDITIONAL_LOOKUP.containsKey(font_family)) {
    195 
    196                                                 if (FONT_WHEEL_ADDITIONAL_LOOKUP.size()>0) {
    197                                                     System.out.print(", ");
     190
     191                                                String font_family = font.getFamily();
     192                                                if (!FONT_WHEEL_ADDITIONAL_LOOKUP.containsKey(font_family)) {
     193
     194                                                        if (FONT_WHEEL_ADDITIONAL_LOOKUP.size() > 0) {
     195                                                                System.out.print(", ");
     196                                                        }
     197                                                        System.out.print("'" + font.getFamily() + "'");
     198
     199                                                        FONT_WHEEL_ADDITIONAL_LOOKUP.put(font_family, font);
     200
     201                                                        int cdut = font.canDisplayUpTo("09AZaz");
     202                                                        if (cdut >= 0) {
     203                                                                // Some problem has occured (should return -1 to show all chars possible)
     204
     205                                                                System.out.println(" [Non-ASCII font]");
     206                                                        }
     207                                                        System.out.flush();
    198208                                                }
    199                                                 System.out.print("'" + font.getFamily() + "'");
    200 
    201                                                 FONT_WHEEL_ADDITIONAL_LOOKUP.put(font_family,font);
    202                                                                                            
    203                                                 int cdut = font.canDisplayUpTo("09AZaz");
    204                                                 if (cdut>=0) {
    205                                                     // Some problem has occured (should return -1 to show all chars possible)
    206                                                
    207                                                     System.out.println(" [Non-ASCII font]");
    208                                                 }
    209                                                 System.out.flush();
    210                                             }
    211                                                
     209
     210                                        } else {
     211                                                System.err.println("Error: Failed to add custom True-Type Font file: " + fontFile);
    212212                                        }
    213                                         else {
    214                                             System.err.println("Error: Failed to add custom True-Type Font file: " + fontFile);
    215                                         }
    216                                                                                
    217                                 }
    218                                 catch (Exception e) {
     213
     214                                } catch (Exception e) {
    219215                                        System.err.println("Failed to load custon font file: " + fontFile);
    220216                                }
     
    222218                }
    223219        }
    224        
     220
    225221        public static void InitFonts() {
    226                
     222
    227223                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    228224
     
    234230                                if (fontFamilyDirs != null) {
    235231
    236                                         if (fontFamilyDirs.length>0) {
     232                                        if (fontFamilyDirs.length > 0) {
    237233                                                System.out.println("Loading custom fonts:");
    238234                                        }
    239235
    240                                         boolean first_item = true;             
     236                                        boolean first_item = true;
    241237                                        for (File fontFamilyDir : fontFamilyDirs) {
    242238                                                if (fontFamilyDir.isDirectory()) {
    243                                                         InitFontFamily(ge,fontFamilyDir);
     239                                                        InitFontFamily(ge, fontFamilyDir);
    244240                                                }
    245241                                        }
    246                                         System.out.println();     
     242                                        System.out.println();
    247243                                }
    248244                        }
    249                 }
    250                 else {
     245                } else {
    251246                        System.err.println("No graphics environment detected.  Skipping the loading of the custom fonts");
    252247                }
     
    254249
    255250        /**
    256      * Similar to parseArgs() in InteractiveWidget. 
    257      * Code based on routine used in Apache Ant:
    258      *   org.apache.tools.ant.types.Commandline::translateCommandline()
    259      * @param toProcess the command line to process.
    260      * @return the command line broken into strings.
    261      * An empty or null toProcess parameter results in a zero sized array.
    262      */
    263     public static String[] parseArgsApache(String toProcess) {
    264         if (toProcess == null || toProcess.length() == 0) {
    265             //no command? no string
    266             return new String[0];
    267         }
    268         // parse with a simple finite state machine
    269 
    270         final int normal = 0;
    271         final int inQuote = 1;
    272         final int inDoubleQuote = 2;
    273         int state = normal;
    274         final StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true);
    275         final ArrayList<String> result = new ArrayList<String>();
    276         final StringBuilder current = new StringBuilder();
    277         boolean lastTokenHasBeenQuoted = false;
    278 
    279         while (tok.hasMoreTokens()) {
    280             String nextTok = tok.nextToken();
    281             switch (state) {
    282             case inQuote:
    283                 if ("\'".equals(nextTok)) {
    284                     lastTokenHasBeenQuoted = true;
    285                     state = normal;
    286                 } else {
    287                     current.append(nextTok);
    288                 }
    289                 break;
    290             case inDoubleQuote:
    291                 if ("\"".equals(nextTok)) {
    292                     lastTokenHasBeenQuoted = true;
    293                     state = normal;
    294                 } else {
    295                     current.append(nextTok);
    296                 }
    297                 break;
    298             default:
    299                 if ("\'".equals(nextTok)) {
    300                     state = inQuote;
    301                 } else if ("\"".equals(nextTok)) {
    302                     state = inDoubleQuote;
    303                 } else if (" ".equals(nextTok)) {
    304                     if (lastTokenHasBeenQuoted || current.length() != 0) {
    305                         result.add(current.toString());
    306                         current.setLength(0);
    307                     }
    308                 } else {
    309                     current.append(nextTok);
    310                 }
    311                 lastTokenHasBeenQuoted = false;
    312                 break;
    313             }
    314         }
    315         if (lastTokenHasBeenQuoted || current.length() != 0) {
    316             result.add(current.toString());
    317         }
    318         if (state == inQuote || state == inDoubleQuote) {
    319             System.err.println("Error: Unbalanced quotes -- failed to parse '" + toProcess + "'");
    320             return null;
    321         }
    322 
    323         return result.toArray(new String[result.size()]);
    324     }
    325 
     251         * Similar to parseArgs() in InteractiveWidget. Code based on routine used in
     252         * Apache Ant: org.apache.tools.ant.types.Commandline::translateCommandline()
     253         *
     254         * @param toProcess
     255         *            the command line to process.
     256         * @return the command line broken into strings. An empty or null toProcess
     257         *         parameter results in a zero sized array.
     258         */
     259        public static String[] parseArgsApache(String toProcess) {
     260                if (toProcess == null || toProcess.length() == 0) {
     261                        // no command? no string
     262                        return new String[0];
     263                }
     264                // parse with a simple finite state machine
     265
     266                final int normal = 0;
     267                final int inQuote = 1;
     268                final int inDoubleQuote = 2;
     269                int state = normal;
     270                final StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true);
     271                final ArrayList<String> result = new ArrayList<String>();
     272                final StringBuilder current = new StringBuilder();
     273                boolean lastTokenHasBeenQuoted = false;
     274
     275                while (tok.hasMoreTokens()) {
     276                        String nextTok = tok.nextToken();
     277                        switch (state) {
     278                        case inQuote:
     279                                if ("\'".equals(nextTok)) {
     280                                        lastTokenHasBeenQuoted = true;
     281                                        state = normal;
     282                                } else {
     283                                        current.append(nextTok);
     284                                }
     285                                break;
     286                        case inDoubleQuote:
     287                                if ("\"".equals(nextTok)) {
     288                                        lastTokenHasBeenQuoted = true;
     289                                        state = normal;
     290                                } else {
     291                                        current.append(nextTok);
     292                                }
     293                                break;
     294                        default:
     295                                if ("\'".equals(nextTok)) {
     296                                        state = inQuote;
     297                                } else if ("\"".equals(nextTok)) {
     298                                        state = inDoubleQuote;
     299                                } else if (" ".equals(nextTok)) {
     300                                        if (lastTokenHasBeenQuoted || current.length() != 0) {
     301                                                result.add(current.toString());
     302                                                current.setLength(0);
     303                                        }
     304                                } else {
     305                                        current.append(nextTok);
     306                                }
     307                                lastTokenHasBeenQuoted = false;
     308                                break;
     309                        }
     310                }
     311                if (lastTokenHasBeenQuoted || current.length() != 0) {
     312                        result.add(current.toString());
     313                }
     314                if (state == inQuote || state == inDoubleQuote) {
     315                        System.err.println("Error: Unbalanced quotes -- failed to parse '" + toProcess + "'");
     316                        return null;
     317                }
     318
     319                return result.toArray(new String[result.size()]);
     320        }
    326321
    327322        /**
     
    371366
    372367        /**
    373          * Sets the maximum width of this Text item when justifcation is used.
    374          * passing in 0 or -1 means there is no maximum width
     368         * Sets the maximum width of this Text item when justifcation is used. passing
     369         * in 0 or -1 means there is no maximum width
    375370         *
    376371         * @param width
    377          *            The maximum width of this item when justification is applied
    378          *            to it.
     372         *            The maximum width of this item when justification is applied to
     373         *            it.
    379374         */
    380375        @Override
     
    394389
    395390        /**
    396          * Returns the maximum width of this Text item when justifcation is used. If
    397          * the width is negative, it means no explicit width has been set
     391         * Returns the maximum width of this Text item when justifcation is used. If the
     392         * width is negative, it means no explicit width has been set
    398393         *
    399394         * @return The maximum width of this Text item when justification is used
     
    422417
    423418        /**
    424          * Sets the justification of this Text item. The given integer should
    425          * correspond to one of the JUSTIFICATION constants defined in Item
     419         * Sets the justification of this Text item. The given integer should correspond
     420         * to one of the JUSTIFICATION constants defined in Item
    426421         *
    427422         * @param just
     
    443438
    444439        /**
    445          * Returns the current justification of this Text item. The default value
    446          * left justification.
     440         * Returns the current justification of this Text item. The default value left
     441         * justification.
    447442         *
    448443         * @return The justification of this Text item
     
    464459
    465460        /**
    466          * Sets the text displayed on the screen to the given String. It does not
    467          * reset the formula, attributeValuePair or other cached values.
     461         * Sets the text displayed on the screen to the given String. It does not reset
     462         * the formula, attributeValuePair or other cached values.
    468463         *
    469464         * @param text
     
    481476
    482477                /*
    483                  * Always clearingCach remove formulas when moving in and out of XRay
    484                  * mode
     478                 * Always clearingCach remove formulas when moving in and out of XRay mode
    485479                 */
    486480                if (clearCache) {
     
    520514
    521515        /**
    522          * Inserts the given String at the start of the first line of this Text
    523          * Item.
     516         * Inserts the given String at the start of the first line of this Text Item.
    524517         *
    525518         * @param text
     
    533526
    534527        /**
    535          * If the first line of text starts with the given String, then it is
    536          * removed otherwise no action is taken.
     528         * If the first line of text starts with the given String, then it is removed
     529         * otherwise no action is taken.
    537530         *
    538531         * @param text
     
    586579
    587580                _text.append(text);
    588                
     581
    589582                rebuild(true);
    590583        }
     
    595588         * @param text
    596589         *            The prefix to check for
    597          * @return True if the first line starts with the given String, False
    598          *         otherwise.
     590         * @return True if the first line starts with the given String, False otherwise.
    599591         */
    600592        public boolean startsWith(String text) {
     
    607599
    608600                if (ignoreCase)
    609                         return _text.toString().toLowerCase()
    610                                         .startsWith(text.toLowerCase());
     601                        return _text.toString().toLowerCase().startsWith(text.toLowerCase());
    611602                else
    612603                        return _text.indexOf(text) == 0;
     
    668659        private Point2D.Float getEdgePosition(int line, boolean start) {
    669660                // if there is no text yet, or the line is invalid
    670                 if (_text == null || _text.length() == 0 || line < 0
    671                                 || line > _textLayouts.size() - 1)
     661                if (_text == null || _text.length() == 0 || line < 0 || line > _textLayouts.size() - 1)
    672662                        return new Point2D.Float(getX(), getY());
    673663
     
    684674
    685675                float x = getX() + caret[0] + getJustOffset(last);
    686                 x = Math
    687                                 .min(
    688                                                 x,
    689                                                 (getX() - Item.MARGIN_RIGHT - (2 * getGravity()) + getBoundsWidth()));
     676                x = Math.min(x, (getX() - Item.MARGIN_RIGHT - (2 * getGravity()) + getBoundsWidth()));
    690677                return new Point2D.Float(x, getY() + y + caret[1]);
    691678        }
     
    728715                        _selectionEnd = _text.length();
    729716
    730                 return _text.substring(Math.min(_selectionStart, _selectionEnd), Math
    731                                 .max(_selectionStart, _selectionEnd));
     717                return _text.substring(Math.min(_selectionStart, _selectionEnd), Math.max(_selectionStart, _selectionEnd));
    732718        }
    733719
     
    787773
    788774        /**
    789          * Inserts the given String into the Text at the position given by the
    790          * mouseX and mouseY coordinates
     775         * Inserts the given String into the Text at the position given by the mouseX
     776         * and mouseY coordinates
    791777         *
    792778         * @param text
     
    803789        }
    804790
    805         public Point2D.Float insertText(String text, float mouseX, float mouseY,
    806                         int insertPos) {
     791        public Point2D.Float insertText(String text, float mouseX, float mouseY, int insertPos) {
    807792                TextHitInfo hit;
    808793                TextLayout current = null;
     
    874859                                        }
    875860                                        // Check if there is a space after the bullet
    876                                         if (index < _text.length() - 1
    877                                                         && _text.charAt(index + 1) == ' ') {
     861                                        if (index < _text.length() - 1 && _text.charAt(index + 1) == ' ') {
    878862                                                // Change the bullet
    879                                                 _text.setCharAt(index, getPreviousBullet(_text
    880                                                                 .charAt(index)));
     863                                                _text.setCharAt(index, getPreviousBullet(_text.charAt(index)));
    881864                                        }
    882865                                        // Remove the spacing at the start
    883866                                        for (int i = 0; i < TAB_STRING.length(); i++) {
    884                                                 if (_text.length() > 0
    885                                                                 && Character.isSpaceChar(_text.charAt(0))) {
     867                                                if (_text.length() > 0 && Character.isSpaceChar(_text.charAt(0))) {
    886868                                                        deleteChar(0);
    887869                                                        pos--;
     
    898880                                        }
    899881                                        // Check if there is a space after the bullet
    900                                         if (index < _text.length() - 1
    901                                                         && _text.charAt(index + 1) == ' ') {
     882                                        if (index < _text.length() - 1 && _text.charAt(index + 1) == ' ') {
    902883                                                char nextBullet = getNextBullet(_text.charAt(index));
    903884                                                // Change the bullet
     
    954935
    955936                float x = getX() + caret[0] + getJustOffset(current);
    956                 x = Math
    957                                 .min(
    958                                                 x,
    959                                                 (getX() - Item.MARGIN_RIGHT - (2 * getGravity()) + getBoundsWidth()));
     937                x = Math.min(x, (getX() - Item.MARGIN_RIGHT - (2 * getGravity()) + getBoundsWidth()));
    960938
    961939                invalidateAll();
    962940
    963                 return new Point2D.Float(Math.round(x), Math.round(getY() + y
    964                                 + caret[1]));
     941                return new Point2D.Float(Math.round(x), Math.round(getY() + y + caret[1]));
    965942        }
    966943
     
    986963        }
    987964
    988         public Point2D.Float moveCursor(int direction, float mouseX, float mouseY,
    989                         boolean setSelection, boolean wholeWord) {
     965        public Point2D.Float moveCursor(int direction, float mouseX, float mouseY, boolean setSelection,
     966                        boolean wholeWord) {
    990967                if (setSelection) {
    991968                        if (!hasSelection()) {
     
    10471024                                                        // Keep going if the char to the left is a
    10481025                                                        // letterOrDigit
    1049                                                         prevChar = _text.charAt(hit.getInsertionIndex() - 1
    1050                                                                         + _lineOffsets.get(line));
    1051                                                 } while (wholeWord
    1052                                                                 && Character.isLetterOrDigit(prevChar));
     1026                                                        prevChar = _text.charAt(hit.getInsertionIndex() - 1 + _lineOffsets.get(line));
     1027                                                } while (wholeWord && Character.isLetterOrDigit(prevChar));
    10531028                                                // TODO Go to the start of the word instead of before
    10541029                                                // the word
    1055                                                 char nextChar = _text.charAt(hit.getInsertionIndex()
    1056                                                                 + _lineOffsets.get(line));
     1030                                                char nextChar = _text.charAt(hit.getInsertionIndex() + _lineOffsets.get(line));
    10571031                                                /*
    10581032                                                 * This takes care of hard line break in
     
    10611035                                                        line--;
    10621036                                                        hit = _textLayouts.get(line)
    1063                                                                         .getNextRightHit(
    1064                                                                                         _textLayouts.get(line)
    1065                                                                                                         .getCharacterCount() - 1);
     1037                                                                        .getNextRightHit(_textLayouts.get(line).getCharacterCount() - 1);
    10661038                                                }
    10671039                                                // This takes care of soft line breaks.
    10681040                                        } else if (line > 0) {
    10691041                                                line--;
    1070                                                 hit = _textLayouts.get(line).getNextRightHit(
    1071                                                                 _textLayouts.get(line).getCharacterCount() - 1);
     1042                                                hit = _textLayouts.get(line).getNextRightHit(_textLayouts.get(line).getCharacterCount() - 1);
    10721043                                                /*
    1073                                                  * Skip the spaces at the end of a line with soft
    1074                                                  * linebreak
     1044                                                 * Skip the spaces at the end of a line with soft linebreak
    10751045                                                 */
    10761046                                                while (hit.getCharIndex() > 0
    1077                                                                 && _text.charAt(_lineOffsets.get(line)
    1078                                                                                 + hit.getCharIndex() - 1) == ' ') {
     1047                                                                && _text.charAt(_lineOffsets.get(line) + hit.getCharIndex() - 1) == ' ') {
    10791048                                                        hit = _textLayouts.get(line).getNextLeftHit(hit);
    10801049                                                }
    10811050                                        }
    10821051                                } else if (direction == RIGHT) {
    1083                                         if (hit.getInsertionIndex() < _textLayouts.get(line)
    1084                                                         .getCharacterCount()) {
     1052                                        if (hit.getInsertionIndex() < _textLayouts.get(line).getCharacterCount()) {
    10851053                                                hit = _textLayouts.get(line).getNextRightHit(hit);
    10861054                                                // Skip whole word if needs be
    1087                                                 while (wholeWord
    1088                                                                 && hit.getCharIndex() > 0
    1089                                                                 && hit.getCharIndex() < _textLayouts.get(line)
    1090                                                                                 .getCharacterCount()
    1091                                                                 && Character.isLetterOrDigit(_text
    1092                                                                                 .charAt(_lineOffsets.get(line)
    1093                                                                                                 + hit.getCharIndex() - 1)))
     1055                                                while (wholeWord && hit.getCharIndex() > 0
     1056                                                                && hit.getCharIndex() < _textLayouts.get(line).getCharacterCount() && Character
     1057                                                                                .isLetterOrDigit(_text.charAt(_lineOffsets.get(line) + hit.getCharIndex() - 1)))
    10941058                                                        hit = _textLayouts.get(line).getNextRightHit(hit);
    10951059                                        } else if (line < _textLayouts.size() - 1) {
     
    11051069                        float y = getLineDrop(current) * line;
    11061070
    1107                         resultPos = new Point2D.Float(getX() + caret[0]
    1108                                         + getJustOffset(current), getY() + y + caret[1]);
     1071                        resultPos = new Point2D.Float(getX() + caret[0] + getJustOffset(current), getY() + y + caret[1]);
    11091072                        break;
    11101073                }
     
    11421105                for (TextLayout text : _textLayouts) {
    11431106                        // calculate X to ensure it is in the shape
    1144                         Rectangle2D bounds = text.getLogicalHighlightShape(0,
    1145                                         text.getCharacterCount()).getBounds2D();
     1107                        Rectangle2D bounds = text.getLogicalHighlightShape(0, text.getCharacterCount()).getBounds2D();
    11461108
    11471109                        if (bounds.getWidth() < 1)
    1148                                 bounds.setRect(bounds.getMinX(), bounds.getMinY(), 10, bounds
    1149                                                 .getHeight());
     1110                                bounds.setRect(bounds.getMinX(), bounds.getMinY(), 10, bounds.getHeight());
    11501111
    11511112                        double x = bounds.getCenterX();
     
    12021163
    12031164        public void setFamily(String newFamily) {
    1204                 String toDecode = newFamily + "-" + getFontStyle() + "-"
    1205                                 + Math.round(getSize());
     1165                String toDecode = newFamily + "-" + getFontStyle() + "-" + Math.round(getSize());
    12061166                setFont(Font.decode(toDecode));
    1207                
     1167
    12081168                setLetterSpacing(this._letter_spacing);
    12091169        }
     
    12281188
    12291189        public static final String[] FONT_WHEEL = { "sansserif", "monospaced", "serif", "dialog", "dialoginput" };
    1230         public static final char[]   FONT_CHARS = { 's', 'm', 't', 'd', 'i' };
    1231 
    1232         // A hashtable to store the font family names that are loaded in through the TTF files
    1233         // provided in the 'assets' folder
    1234         public static HashMap<String, Font> FONT_WHEEL_ADDITIONAL_LOOKUP = new HashMap<>();
    1235    
     1190        public static final char[] FONT_CHARS = { 's', 'm', 't', 'd', 'i' };
     1191
     1192        // A hashtable to store the font family names that are loaded in through the TTF
     1193        // files
     1194        // provided in the 'assets' folder
     1195        public static HashMap<String, Font> FONT_WHEEL_ADDITIONAL_LOOKUP = new HashMap<>();
     1196
    12361197        private static final int NEARBY_GRAVITY = 2;
    12371198
     
    13081269                } else if (newFace.equals("italic") || newFace.equals("i")) {
    13091270                        setFont(getPaintFont().deriveFont(Font.ITALIC));
    1310                 } else if (newFace.equals("bolditalic") || newFace.equals("italicbold")
    1311                                 || newFace.equals("bi") || newFace.equals("ib")) {
     1271                } else if (newFace.equals("bolditalic") || newFace.equals("italicbold") || newFace.equals("bi")
     1272                                || newFace.equals("ib")) {
    13121273                        setFont(getPaintFont().deriveFont(Font.BOLD + Font.ITALIC));
    13131274                }
     
    13351296                        for (int offset : _lineOffsets) {
    13361297                                if (offset != last) {
    1337                                         list
    1338                                                         .add(_text.substring(last, offset).replaceAll("\n",
    1339                                                                         ""));
     1298                                        list.add(_text.substring(last, offset).replaceAll("\n", ""));
    13401299                                }
    13411300                                last = offset;
     
    13991358        private float getLineDrop(TextLayout layout) {
    14001359                if (getSpacing() < 0)
    1401                         return layout.getAscent() + layout.getDescent()
    1402                                         + layout.getLeading();
     1360                        return layout.getAscent() + layout.getDescent() + layout.getLeading();
    14031361
    14041362                return layout.getAscent() + layout.getDescent() + getSpacing();
     
    14171375         *
    14181376         * @param spacing
    1419          *            Additional spacing to add between letters. See {@link java.awt.font.TextAttribute#TRACKING}
     1377         *            Additional spacing to add between letters. See
     1378         *            {@link java.awt.font.TextAttribute#TRACKING}
    14201379         */
    14211380        public void setLetterSpacing(float spacing) {
     
    14231382                HashMap<TextAttribute, Object> attr = new HashMap<TextAttribute, Object>();
    14241383                attr.put(TextAttribute.TRACKING, spacing);
    1425                
     1384
    14261385                if (this._font == null) {
    14271386                        this._font = Font.decode(DEFAULT_FONT);
     
    14321391
    14331392        /**
    1434          * @return The spacing (proportional to the font size) between letters. See {@link java.awt.font.TextAttribute#TRACKING}
     1393         * @return The spacing (proportional to the font size) between letters. See
     1394         *         {@link java.awt.font.TextAttribute#TRACKING}
    14351395         */
    14361396        public float getLetterSpacing() {
     
    14461406        }
    14471407
    1448         //@Override
     1408        // @Override
    14491409        public boolean intersectsOLD(Polygon p) {
    14501410                if (super.intersects(p)) {
     
    14531413                        for (TextLayout text : _textLayouts) {
    14541414                                // check left and right of each box
    1455                                 Rectangle2D textOutline = text.getLogicalHighlightShape(0,
    1456                                                 text.getCharacterCount()).getBounds2D();
    1457                                 textOutline
    1458                                                 .setRect(textOutline.getX() + getX() - 1, textOutline
    1459                                                                 .getY()
    1460                                                                 + textY - 1, textOutline.getWidth() + 2,
    1461                                                                 textOutline.getHeight() + 2);
     1415                                Rectangle2D textOutline = text.getLogicalHighlightShape(0, text.getCharacterCount()).getBounds2D();
     1416                                textOutline.setRect(textOutline.getX() + getX() - 1, textOutline.getY() + textY - 1,
     1417                                                textOutline.getWidth() + 2, textOutline.getHeight() + 2);
    14621418                                if (p.intersects(textOutline))
    14631419                                        return true;
     
    14671423                return false;
    14681424        }
    1469        
    1470         // The following version of intersect uses a tighter definition for the text, based on
    1471     @Override
     1425
     1426        // The following version of intersect uses a tighter definition for the text,
     1427        // based on
     1428        @Override
    14721429        public boolean intersects(Polygon p) {
    14731430                if (super.intersects(p)) {
    1474 //                      float textY = getY();
     1431                        // float textY = getY();
    14751432
    14761433                        for (TextLayout text : _textLayouts) {
    1477                                
     1434
    14781435                                Rectangle text_pixel_bounds_rect = this.getPixelBounds(text);
    1479                                
     1436
    14801437                                if (p.intersects(text_pixel_bounds_rect)) {
    14811438                                        return true;
     
    14831440                        }
    14841441                }
    1485                
     1442
    14861443                return false;
    14871444        }
     
    15021459
    15031460                // Check if its outside the top and left and bottom bounds
    1504                 if (outline.getX() - mouseX > gravity
    1505                                 || outline.getY() - mouseY > gravity
     1461                if (outline.getX() - mouseX > gravity || outline.getY() - mouseY > gravity
    15061462                                || mouseY - (outline.getY() + outline.getHeight()) > gravity
    15071463                                || mouseX - (outline.getX() + outline.getWidth()) > gravity) {
     
    15111467                for (TextLayout text : _textLayouts) {
    15121468                        // check left and right of each box
    1513                         Rectangle2D textOutline = text.getLogicalHighlightShape(0,
    1514                                         text.getCharacterCount()).getBounds2D();
     1469                        Rectangle2D textOutline = text.getLogicalHighlightShape(0, text.getCharacterCount()).getBounds2D();
    15151470
    15161471                        // check if the cursor is within the top, bottom and within the
     
    15181473                        int justOffset = getJustOffset(text);
    15191474
    1520                         if (mouseY - textY > textOutline.getY()
    1521                                         && mouseY - textY < textOutline.getY()
    1522                                                         + textOutline.getHeight()
    1523                                         && mouseX - textX - justOffset < textOutline.getWidth()
    1524                                                         + gravity + Item.MARGIN_RIGHT
     1475                        if (mouseY - textY > textOutline.getY() && mouseY - textY < textOutline.getY() + textOutline.getHeight()
     1476                                        && mouseX - textX - justOffset < textOutline.getWidth() + gravity + Item.MARGIN_RIGHT
    15251477                        /* &&(justOffset == 0 || mouseX > textX + justOffset - gravity ) */)
    15261478                                return true;
     
    15551507
    15561508                float y = -1;
    1557                
     1509
    15581510                // Fix concurrency error in ScaleFrameset
    15591511                List<TextLayout> tmpTextLayouts;
    1560                 synchronized(_textLayouts) {
     1512                synchronized (_textLayouts) {
    15611513                        tmpTextLayouts = new LinkedList<TextLayout>(_textLayouts);
    15621514                }
    15631515
    15641516                for (TextLayout layout : tmpTextLayouts) {
    1565                         Rectangle2D bounds = layout.getLogicalHighlightShape(0,
    1566                                         layout.getCharacterCount()).getBounds2D();
    1567                
     1517                        Rectangle2D bounds = layout.getLogicalHighlightShape(0, layout.getCharacterCount()).getBounds2D();
     1518
    15681519                        if (y < 0)
    15691520                                y = 0;
     
    15911542
    15921543                _poly.translate(getX(), getY());
    1593                                                
    1594                 if(preChangeWidth != 0 && preChangeWidth != _poly.getBounds().width)
    1595                         if(_poly.getBounds().width > preChangeWidth) MagneticConstraints.getInstance().textGrown(this, _poly.getBounds().width - preChangeWidth);
    1596                         else MagneticConstraints.getInstance().textShrunk(this, preChangeWidth - _poly.getBounds().width);
     1544
     1545                if (preChangeWidth != 0 && preChangeWidth != _poly.getBounds().width)
     1546                        if (_poly.getBounds().width > preChangeWidth)
     1547                                MagneticConstraints.getInstance().textGrown(this, _poly.getBounds().width - preChangeWidth);
     1548                        else
     1549                                MagneticConstraints.getInstance().textShrunk(this, preChangeWidth - _poly.getBounds().width);
    15971550        }
    15981551
     
    16301583
    16311584                if (_lineBreaker == null || newLinebreakerAlways) {
    1632                         AttributedString paragraphText = new AttributedString(_text
    1633                                         .toString());
     1585                        AttributedString paragraphText = new AttributedString(_text.toString());
    16341586                        paragraphText.addAttribute(TextAttribute.FONT, getPaintFont());
    16351587                        frc = new FontRenderContext(null, true, true);
     
    16371589                }
    16381590
    1639                 /* float width = Float.MAX_VALUE;
    1640 
    1641                 if (limitWidth) {
    1642                         width = getAbsoluteWidth();
    1643                         // else if (getMaxWidth() > 0)
    1644                         // width = Math.max(50, getMaxWidth() - getX()
    1645                         // - Item.MARGIN_RIGHT);
    1646                 } */
     1591                /*
     1592                 * float width = Float.MAX_VALUE;
     1593                 *
     1594                 * if (limitWidth) { width = getAbsoluteWidth(); // else if (getMaxWidth() > 0)
     1595                 * // width = Math.max(50, getMaxWidth() - getX() // - Item.MARGIN_RIGHT); }
     1596                 */
    16471597
    16481598                _textLayouts.clear();
     
    16521602
    16531603                TextLayout layout;
    1654                
     1604
    16551605                float width;
    16561606                float lineHeight = Float.NaN;
    16571607                List<Point[]> lines = null;
    1658                
    1659                 if(_autoWrap || ExperimentalFeatures.AutoWrap.get()) {
    1660                 lines = new LinkedList<Point[]>();
    1661                 if(DisplayIO.getCurrentFrame() == null) {
    1662                         return;
    1663                 }
    1664                 for(Item item : DisplayIO.getCurrentFrame().getItems()) {
    1665                                 if(item instanceof Line) {
    1666                                         lines.add(new Point[] { ((Line) item).getStartItem().getPosition(), ((Line) item).getEndItem().getPosition() });
    1667                                 }
    1668                                 if(item instanceof Picture) {
    1669                                         lines.add(new Point[] { item.getPosition(), new Point(item.getX(), item.getY() + item.getHeight()) });
    1670                                 }
    1671                 }
    1672                 for(Item item : FreeItems.getInstance()) {
    1673                                 if(item instanceof Line) {
    1674                                         lines.add(new Point[] { ((Line) item).getStartItem().getPosition(), ((Line) item).getEndItem().getPosition() });
    1675                                 }
    1676                                 if(item instanceof Picture) {
    1677                                         lines.add(new Point[] { item.getPosition(), new Point(item.getX(), item.getY() + item.getHeight()) });
    1678                                 }
    1679                 }
    1680                 width = getLineWidth(getX(), getY(), lines);
     1608
     1609                if (_autoWrap || ExperimentalFeatures.AutoWrap.get()) {
     1610                        lines = new LinkedList<Point[]>();
     1611                        if (DisplayIO.getCurrentFrame() == null) {
     1612                                return;
     1613                        }
     1614                        for (Item item : DisplayIO.getCurrentFrame().getItems()) {
     1615                                if (item instanceof Line) {
     1616                                        lines.add(new Point[] { ((Line) item).getStartItem().getPosition(),
     1617                                                        ((Line) item).getEndItem().getPosition() });
     1618                                }
     1619                                if (item instanceof Picture) {
     1620                                        lines.add(
     1621                                                        new Point[] { item.getPosition(), new Point(item.getX(), item.getY() + item.getHeight()) });
     1622                                }
     1623                        }
     1624                        for (Item item : FreeItems.getInstance()) {
     1625                                if (item instanceof Line) {
     1626                                        lines.add(new Point[] { ((Line) item).getStartItem().getPosition(),
     1627                                                        ((Line) item).getEndItem().getPosition() });
     1628                                }
     1629                                if (item instanceof Picture) {
     1630                                        lines.add(
     1631                                                        new Point[] { item.getPosition(), new Point(item.getX(), item.getY() + item.getHeight()) });
     1632                                }
     1633                        }
     1634                        width = getLineWidth(getX(), getY(), lines);
    16811635                } else {
    16821636                        width = Float.MAX_VALUE;
    1683                 if (limitWidth) {
    1684                         if(_maxWidth == null) {
    1685                                 width = FrameGraphics.getMaxFrameSize().width - getX();
    1686                         } else {
    1687                                 width = getAbsoluteWidth();
    1688                         }
    1689                         // else if (getMaxWidth() > 0)
    1690                         // width = Math.max(50, getMaxWidth() - getX()
    1691                         // - Item.MARGIN_RIGHT);
    1692                 }
    1693                 }
    1694                
     1637                        if (limitWidth) {
     1638                                if (_maxWidth == null) {
     1639                                        width = FrameGraphics.getMaxFrameSize().width - getX();
     1640                                } else {
     1641                                        width = getAbsoluteWidth();
     1642                                }
     1643                                // else if (getMaxWidth() > 0)
     1644                                // width = Math.max(50, getMaxWidth() - getX()
     1645                                // - Item.MARGIN_RIGHT);
     1646                        }
     1647                }
     1648
    16951649                _lineBreaker.setPosition(0);
    16961650                boolean requireNextWord = false;
     
    16981652                // --- Get the output of the LineBreakMeasurer and store it in a
    16991653                while (_lineBreaker.getPosition() < _text.length()) {
    1700                        
    1701                         if(_autoWrap || ExperimentalFeatures.AutoWrap.get()) {
     1654
     1655                        if (_autoWrap || ExperimentalFeatures.AutoWrap.get()) {
    17021656                                requireNextWord = width < FrameGraphics.getMaxFrameSize().width - getX();
    17031657                        }
    1704                        
     1658
    17051659                        layout = _lineBreaker.nextLayout(width, _text.length(), requireNextWord);
    1706                        
     1660
    17071661                        // lineBreaker does not break on newline
    17081662                        // characters so they have to be check manually
    17091663                        int start = _lineOffsets.get(_lineOffsets.size() - 1);
    1710                        
    1711                         // int y = getY() + (getLineDrop(layout) * (_lineOffsets.size() - 1) 
    1712                        
     1664
     1665                        // int y = getY() + (getLineDrop(layout) * (_lineOffsets.size() - 1)
     1666
    17131667                        // check through the current line for newline characters
    17141668                        for (int i = start + 1; i < _text.length(); i++) {
     
    17211675
    17221676                        _lineOffsets.add(_lineBreaker.getPosition());
    1723                        
    1724                         if(layout == null) {
     1677
     1678                        if (layout == null) {
    17251679                                layout = new TextLayout(" ", getPaintFont(), frc);
    17261680                        }
     
    17291683                                        && _lineBreaker.getPosition() < _text.length())
    17301684                                layout = layout.getJustifiedLayout(width);
    1731                        
     1685
    17321686                        _textLayouts.add(layout);
    1733                                                
    1734                         if(_autoWrap || ExperimentalFeatures.AutoWrap.get()) {
    1735                                
    1736                         if(lineHeight != Float.NaN) {
    1737                                 lineHeight = getLineDrop(layout);
    1738                         }
    1739                         width = getLineWidth(getX(), getY() + (lineHeight * (_textLayouts.size() - 1)), lines);
     1687
     1688                        if (_autoWrap || ExperimentalFeatures.AutoWrap.get()) {
     1689
     1690                                if (lineHeight != Float.NaN) {
     1691                                        lineHeight = getLineDrop(layout);
     1692                                }
     1693                                width = getLineWidth(getX(), getY() + (lineHeight * (_textLayouts.size() - 1)), lines);
    17401694                        }
    17411695                }
     
    17441698
    17451699        }
    1746        
     1700
    17471701        private float getLineWidth(int x, float y, List<Point[]> lines) {
    17481702                float width = FrameGraphics.getMaxFrameSize().width;
    1749                 for(Point[] l : lines) {
     1703                for (Point[] l : lines) {
    17501704                        // check for lines that cross over our y
    1751                         if((l[0].y >= y && l[1].y <= y) || (l[0].y <= y && l[1].y >= y)) {
     1705                        if ((l[0].y >= y && l[1].y <= y) || (l[0].y <= y && l[1].y >= y)) {
    17521706                                float dX = l[0].x - l[1].x;
    17531707                                float dY = l[0].y - l[1].y;
    17541708                                float newWidth;
    1755                                 if(dX == 0) {
     1709                                if (dX == 0) {
    17561710                                        newWidth = l[0].x;
    1757                                 } else if(dY == 0) {
     1711                                } else if (dY == 0) {
    17581712                                        newWidth = Math.min(l[0].x, l[1].x);
    17591713                                } else {
     
    17621716                                }
    17631717                                // System.out.println("dY:" + dY + " dX:" + dX + " width:" + newWidth);
    1764                                 if(newWidth < x) {
    1765                                         continue;
     1718                                if (newWidth < x) {
     1719                                        continue;
    17661720                                }
    1767                                 if(newWidth < width) {
     1721                                if (newWidth < width) {
    17681722                                        width = newWidth;
    17691723                                }
     
    18071761                // if the selection is before this line, return null
    18081762                if (_lineOffsets.get(line) < selectionLeft
    1809                                 && _lineOffsets.get(line)
    1810                                                 + _textLayouts.get(line).getCharacterCount() < selectionLeft)
     1763                                && _lineOffsets.get(line) + _textLayouts.get(line).getCharacterCount() < selectionLeft)
    18111764                        return null;
    18121765
     
    18201773                // int end = Math.min(_lineOffsets.get(line) +
    18211774                // _textLayouts.get(line).getCharacterCount(), _selectionEnd);
    1822                 int end = Math.min(selectionRight - _lineOffsets.get(line),
    1823                                 +_textLayouts.get(line).getCharacterCount());
     1775                int end = Math.min(selectionRight - _lineOffsets.get(line), +_textLayouts.get(line).getCharacterCount());
    18241776
    18251777                // System.out.println(line + ": " + start + "x" + end + " (" +
     
    18401792                 * Color main = getPaintColor(); Color back = getPaintBackgroundColor();
    18411793                 *
    1842                  * if (Math.abs(main.getRed() - back.getRed()) < 10 &&
    1843                  * Math.abs(main.getGreen() - back.getGreen()) < 10 &&
    1844                  * Math.abs(main.getBlue() - back.getBlue()) < 10) { selection = new
    1845                  * Color(Math.abs(255 - main.getRed()), Math .abs(255 -
    1846                  * main.getGreen()), Math.abs(255 - main.getBlue())); } else { selection =
    1847                  * new Color((main.getRed() + (back.getRed() * 2)) / 3, (main.getGreen() +
    1848                  * (back.getGreen() * 2)) / 3, (main .getBlue() + (back.getBlue() * 2)) /
    1849                  * 3); }
     1794                 * if (Math.abs(main.getRed() - back.getRed()) < 10 && Math.abs(main.getGreen()
     1795                 * - back.getGreen()) < 10 && Math.abs(main.getBlue() - back.getBlue()) < 10) {
     1796                 * selection = new Color(Math.abs(255 - main.getRed()), Math .abs(255 -
     1797                 * main.getGreen()), Math.abs(255 - main.getBlue())); } else { selection = new
     1798                 * Color((main.getRed() + (back.getRed() * 2)) / 3, (main.getGreen() +
     1799                 * (back.getGreen() * 2)) / 3, (main .getBlue() + (back.getBlue() * 2)) / 3); }
    18501800                 */
    18511801                int green = 160;
     
    18761826                if (_text == null || _text.length() == 0)
    18771827                        return;
    1878                
    1879                 if(_autoWrap || ExperimentalFeatures.AutoWrap.get()) {
     1828
     1829                if (_autoWrap || ExperimentalFeatures.AutoWrap.get()) {
    18801830                        invalidateAll();
    1881                
     1831
    18821832                        rebuild(true);
    18831833                } else if (_textLayouts.size() < 1) {
     
    19011851                        Color bgc = getBackgroundColor();
    19021852                        if (_alpha > 0) {
    1903                                 bgc = new Color(bgc.getRed(), bgc.getGreen(), bgc.getBlue(),
    1904                                                 _alpha);
     1853                                bgc = new Color(bgc.getRed(), bgc.getGreen(), bgc.getBlue(), _alpha);
    19051854                        }
    19061855                        g.setColor(bgc);
     
    19121861                                if (s != null) {
    19131862                                        Rectangle b = s.getBounds();
    1914                                         GradientPaint gp = new GradientPaint(
    1915                                                         (int) (b.x + b.width * 0.3), b.y, bgc,
     1863                                        GradientPaint gp = new GradientPaint((int) (b.x + b.width * 0.3), b.y, bgc,
    19161864                                                        (int) (b.x + b.width * 1.3), b.y, gradientColor);
    19171865                                        g.setPaint(gp);
     
    19361884                        Point2D.Float start = getEdgePosition(0, true);
    19371885                        Point2D.Float end = getEdgePosition(0, false);
    1938                         g.drawLine(Math.round(start.x), Math.round(start.y), Math
    1939                                         .round(end.x), Math.round(end.y));
     1886                        g.drawLine(Math.round(start.x), Math.round(start.y), Math.round(end.x), Math.round(end.y));
    19401887                }
    19411888
    19421889                if (isHighlighted()) {
    19431890                        g.setColor(getPaintHighlightColor());
    1944                         Stroke highlightStroke = new BasicStroke(
    1945                                         (float) getHighlightThickness(), CAP, JOIN);
     1891                        Stroke highlightStroke = new BasicStroke((float) getHighlightThickness(), CAP, JOIN);
    19461892                        g.setStroke(highlightStroke);
    19471893                        if (HighlightMode.Enclosed.equals(getHighlightMode()))
     
    19581904                g.setColor(c);
    19591905
    1960                 Color selection = getSelectionColor(FrameMouseActions
    1961                                 .getLastMouseButton());
     1906                Color selection = getSelectionColor(FrameMouseActions.getLastMouseButton());
    19621907
    19631908                // width -= getX();
     
    19821927                                }
    19831928
    1984                                 int ldx = 1+getX()+getJustOffset(layout); // Layout draw x
    1985                                
     1929                                int ldx = 1 + getX() + getJustOffset(layout); // Layout draw x
     1930
    19861931                                boolean debug = false;
    19871932                                if (debug) {
    1988                                         g.setColor(new Color(c.getRed(),c.getGreen(),c.getBlue(),40));
     1933                                        g.setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), 40));
    19891934                                        Rectangle layout_rect = layout.getPixelBounds(null, ldx, y);
    19901935                                        g.fillRect(layout_rect.x, layout_rect.y, layout_rect.width, layout_rect.height);
    19911936                                        g.setColor(c);
    19921937                                }
    1993                                
    1994                                
     1938
    19951939                                layout.draw(g, ldx, y);
    19961940
    19971941                                /*
    1998                                  * AffineTransform at = new AffineTransform(); AffineTransform
    1999                                  * orig = g.getTransform(); at.translate(getX() +
    2000                                  * getJustOffset(layout), y); g.setTransform(at);
    2001                                  * g.draw(layout.getLogicalHighlightShape(0,
     1942                                 * AffineTransform at = new AffineTransform(); AffineTransform orig =
     1943                                 * g.getTransform(); at.translate(getX() + getJustOffset(layout), y);
     1944                                 * g.setTransform(at); g.draw(layout.getLogicalHighlightShape(0,
    20021945                                 * layout.getCharacterCount())); g.setTransform(orig); /*
    2003                                  * if(_text.charAt(_lineOffsets.get(line) +
    2004                                  * (layout.getCharacterCount() - 1)) == '\t'){ tab = true; x =
    2005                                  * (int) (getX() + x + 20 + layout.getVisibleAdvance()); }else{
     1946                                 * if(_text.charAt(_lineOffsets.get(line) + (layout.getCharacterCount() - 1)) ==
     1947                                 * '\t'){ tab = true; x = (int) (getX() + x + 20 + layout.getVisibleAdvance());
     1948                                 * }else{
    20061949                                 */
    20071950                                y += getLineDrop(layout);
     
    20972040                        if (isAnnotation())
    20982041                                return;
    2099                         if (!isLineEnd() && _text.length() > 0
    2100                                         && _text.charAt(0) == DEFAULT_BULLET) {
    2101                                 newPoint.setLocation(insertText(""
    2102                                                 + (char) KeyEvent.VK_BACK_SPACE, mouseX, mouseY, 1));
     2042                        if (!isLineEnd() && _text.length() > 0 && _text.charAt(0) == DEFAULT_BULLET) {
     2043                                newPoint.setLocation(insertText("" + (char) KeyEvent.VK_BACK_SPACE, mouseX, mouseY, 1));
    21032044                                if (_text.length() > 0 && _text.charAt(0) == ' ')
    2104                                         newPoint.setLocation(insertText(""
    2105                                                         + (char) KeyEvent.VK_BACK_SPACE, newPoint.x,
    2106                                                         newPoint.y, 1));
     2045                                        newPoint.setLocation(insertText("" + (char) KeyEvent.VK_BACK_SPACE, newPoint.x, newPoint.y, 1));
    21072046                        } else {
    21082047                                newPoint.setLocation(insertText("@", mouseX, mouseY, 0));
     
    21132052                                return;
    21142053                        if (!isLineEnd() && _text.charAt(0) == '@') {
    2115                                 newPoint.setLocation(insertText(""
    2116                                                 + (char) KeyEvent.VK_BACK_SPACE, mouseX, mouseY, 1));
    2117                                 newPoint.setLocation(insertText(DEFAULT_BULLET_STRING,
    2118                                                 newPoint.x, newPoint.y, 0));
     2054                                newPoint.setLocation(insertText("" + (char) KeyEvent.VK_BACK_SPACE, mouseX, mouseY, 1));
     2055                                newPoint.setLocation(insertText(DEFAULT_BULLET_STRING, newPoint.x, newPoint.y, 0));
    21192056                        } else {
    2120                                 newPoint.setLocation(insertText(""
    2121                                                 + (char) KeyEvent.VK_BACK_SPACE, mouseX, mouseY, 1));
     2057                                newPoint.setLocation(insertText("" + (char) KeyEvent.VK_BACK_SPACE, mouseX, mouseY, 1));
    21222058                        }
    21232059                }
     
    21782114                String s = _text.toString().toLowerCase();
    21792115                if (s.length() > 0 && s.indexOf("@") == 0) {
    2180                         if (s.equals("@old") || s.equals("@ao")
    2181                                         || s.equals("@itemtemplate") || s.equals("@parent")
    2182                                         || s.equals("@next") || s.equals("@previous")
    2183                                         || s.equals("@first") || s.equals("@i") || s.equals("@iw")
    2184                                         || s.equals("@f"))
     2116                        if (s.equals("@old") || s.equals("@ao") || s.equals("@itemtemplate") || s.equals("@parent")
     2117                                        || s.equals("@next") || s.equals("@previous") || s.equals("@first") || s.equals("@i")
     2118                                        || s.equals("@iw") || s.equals("@f"))
    21852119                                return true;
    21862120                }
     
    22452179                        setRightMargin(modelFrame.getNameItem().getX() - MARGIN_LEFT, true);
    22462180                } else {
    2247                         System.out
    2248                                         .print("Error: text.resetTitlePosition, getParent or currentFrame returned null");
     2181                        System.out.print("Error: text.resetTitlePosition, getParent or currentFrame returned null");
    22492182                        setRightMargin(MARGIN_LEFT, true);
    22502183                }
     
    22832216                Text template = this.copy();
    22842217                template.setID(-1);
    2285                 // reset width of global templates so the widths of the items on the settings frames don't cause issues
    2286                 // this is in response to the fact that FrameCreator.addItem() sets rightMargin when it adds items
     2218                // reset width of global templates so the widths of the items on the settings
     2219                // frames don't cause issues
     2220                // this is in response to the fact that FrameCreator.addItem() sets rightMargin
     2221                // when it adds items
    22872222                template.setWidth(null);
    22882223                /*
    2289                  * The template must have text otherwise the bounds height will be
    2290                  * zero!! This will stop escape drop down from working if there is no
    2291                  * item template
     2224                 * The template must have text otherwise the bounds height will be zero!! This
     2225                 * will stop escape drop down from working if there is no item template
    22922226                 */
    22932227                template.setText("@");
     
    23082242                        for (TextLayout text : _textLayouts) {
    23092243                                // check left and right of each box
    2310                                 Rectangle2D textOutline = text.getLogicalHighlightShape(0,
    2311                                                 text.getCharacterCount()).getBounds2D();
     2244                                Rectangle2D textOutline = text.getLogicalHighlightShape(0, text.getCharacterCount()).getBounds2D();
    23122245
    23132246                                // check if the cursor is within the top, bottom and within the
    23142247                                // gravity of right
    23152248                                if (y - textY > textOutline.getY() - NEAR_DISTANCE
    2316                                                 && y - textY < textOutline.getY()
    2317                                                                 + textOutline.getHeight() + NEAR_DISTANCE
     2249                                                && y - textY < textOutline.getY() + textOutline.getHeight() + NEAR_DISTANCE
    23182250                                                && x - textX < textOutline.getWidth() + NEAR_DISTANCE)
    23192251                                        return true;
     
    23422274                }
    23432275        }
    2344        
     2276
    23452277        private void clipFrameMargin() {
    23462278                if (!hasFixedWidth()) {
    23472279                        int frameWidth = FrameGraphics.getMaxFrameSize().width;
    23482280                        /*
    2349                          * Only change width if it is more than 150 pixels from the right of
    2350                          * the screen
     2281                         * Only change width if it is more than 150 pixels from the right of the screen
    23512282                         */
    23522283                        if (!_text.toString().contains(" ")) {
     
    23602291                }
    23612292        }
    2362        
     2293
    23632294        public void justify(boolean fixWidth, Polygon enclosure) {
    23642295                // if autowrap is on, wrapping is done every time we draw
    2365                 if(ExperimentalFeatures.AutoWrap.get()) {
     2296                if (ExperimentalFeatures.AutoWrap.get()) {
    23662297                        return;
    23672298                }
    2368                
     2299
    23692300                Integer width = FrameGraphics.getMaxFrameSize().width;
    23702301
     
    23842315                // on the frame
    23852316                String widthString;
    2386                 if ((widthString = getParentOrCurrentFrame().getAnnotationValue(
    2387                                 "maxwidth")) != null) {
     2317                if ((widthString = getParentOrCurrentFrame().getAnnotationValue("maxwidth")) != null) {
    23882318                        try {
    23892319                                int oldWidth = getWidth();
     
    23992329        public void justify(boolean fixWidth) {
    24002330                // if autowrap is on, wrapping is done every time we draw
    2401                 if(ExperimentalFeatures.AutoWrap.get()) {
     2331                if (ExperimentalFeatures.AutoWrap.get()) {
    24022332                        return;
    24032333                }
     
    24522382                if (!text.startsWith("@"))
    24532383                        return false;
    2454                 return text.startsWith("@o") || text.startsWith("@ao")
    2455                                 || text.startsWith("@v") || text.startsWith("@av");
     2384                return text.startsWith("@o") || text.startsWith("@ao") || text.startsWith("@v") || text.startsWith("@av");
    24562385        }
    24572386
     
    25052434                                        }
    25062435                                } // else {
    2507                                 // Add anonomous vars
     2436                                        // Add anonomous vars
    25082437                                try {
    25092438                                        double value = pair.getDoubleValue();
     
    25282457                        // If the frame is linked add vector variable for the frame
    25292458                        if (lowercaseFormula.contains("$frame")) {
    2530                                 myParser.addVectorVariable(frame.getNonAnnotationItems(true),
    2531                                                 "$frame");
     2459                                myParser.addVectorVariable(frame.getNonAnnotationItems(true), "$frame");
    25322460                        }
    25332461                }
     
    25532481                        }
    25542482                } catch (Throwable e) {
    2555                         //e.printStackTrace();
     2483                        // e.printStackTrace();
    25562484                        String formula2 = getFormula();
    25572485                        this.setText(formula2);
     
    25662494
    25672495        /**
    2568          * Gets items which are in the same enclosure as this item.
    2569          * In the event more than one enclosure meets this criteria, then
    2570          * the one returned is the one with the smallest area.
    2571          * TODO: Improve the efficiency of this method
     2496         * Gets items which are in the same enclosure as this item. In the event more
     2497         * than one enclosure meets this criteria, then the one returned is the one with
     2498         * the smallest area. TODO: Improve the efficiency of this method
    25722499         *
    25732500         * @return
     
    25802507                for (Item i : parent.getVisibleItems()) {
    25812508                        /*
    2582                          * Go through all the enclosures looking for one that includes this
    2583                          * item
     2509                         * Go through all the enclosures looking for one that includes this item
    25842510                         */
    25852511                        if (!seen.contains(i) && i.isEnclosed()) {
     
    25892515                                // Check it is smaller than any other enclosure found containing
    25902516                                // this item
    2591                                 if (enclosed.contains(this)
    2592                                                 && i.getEnclosedArea() < enclosureArea) {
     2517                                if (enclosed.contains(this) && i.getEnclosedArea() < enclosureArea) {
    25932518                                        sameEnclosure = enclosed;
    25942519                                }
     
    26012526                return sameEnclosure;
    26022527        }
    2603        
    2604         /**
    2605          * Returns true if items of the parent frame should be recalculated when
    2606          * this item is modified
     2528
     2529        /**
     2530         * Returns true if items of the parent frame should be recalculated when this
     2531         * item is modified
    26072532         */
    26082533        public boolean recalculateWhenChanged() {
     
    26392564                invalidateFill();
    26402565                invalidateCommonTrait(ItemAppearence.PreMoved);
    2641                
     2566
    26422567                this._anchorLeft = anchor;
    26432568                this._anchorRight = null;
    2644                
     2569
    26452570                int oldX = getX();
    26462571                if (anchor != null) {
     
    26592584                        // Subtract off the link width
    26602585                        if (anchor != null) {
    2661                                 setX(FrameGraphics.getMaxFrameSize().width - anchor
    2662                                                 - getBoundsWidth() + getLeftMargin());
     2586                                setX(FrameGraphics.getMaxFrameSize().width - anchor - getBoundsWidth() + getLeftMargin());
    26632587                        }
    26642588                        return;
     
    26662590                invalidateFill();
    26672591                invalidateCommonTrait(ItemAppearence.PreMoved);
    2668                
     2592
    26692593                this._anchorRight = anchor;
    26702594                this._anchorLeft = null;
    2671                
     2595
    26722596                int oldX = getX();
    26732597                if (anchor != null) {
    2674                         float deltaX = FrameGraphics.getMaxFrameSize().width - anchor
    2675                                         - getBoundsWidth() + getLeftMargin() - oldX;
     2598                        float deltaX = FrameGraphics.getMaxFrameSize().width - anchor - getBoundsWidth() + getLeftMargin() - oldX;
    26762599                        anchorConnected(AnchorEdgeType.Right, deltaX);
    26772600                }
     
    26802603                invalidateFill();
    26812604        }
    2682 
    2683 
    26842605
    26852606        @Override
     
    26942615                invalidateFill();
    26952616                invalidateCommonTrait(ItemAppearence.PreMoved);
    2696                
     2617
    26972618                this._anchorTop = anchor;
    26982619                this._anchorBottom = null;
    2699                
     2620
    27002621                int oldY = getY();
    27012622                if (anchor != null) {
     
    27132634                        super.setAnchorBottom(anchor);
    27142635                        if (anchor != null) {
    2715                                 setY(FrameGraphics.getMaxFrameSize().height - (anchor + this.getBoundsHeight() - _textLayouts.get(0).getAscent() - _textLayouts.get(0).getDescent()));
     2636                                setY(FrameGraphics.getMaxFrameSize().height - (anchor + this.getBoundsHeight()
     2637                                                - _textLayouts.get(0).getAscent() - _textLayouts.get(0).getDescent()));
    27162638                        }
    27172639                        return;
     
    27192641                invalidateFill();
    27202642                invalidateCommonTrait(ItemAppearence.PreMoved);
    2721                
     2643
    27222644                this._anchorBottom = anchor;
    27232645                this._anchorTop = null;
    2724                
     2646
    27252647                int oldY = getY();
    27262648                if (anchor != null) {
     
    27422664                        setWidth(Math.round(width * scale));
    27432665                }
    2744                
     2666
    27452667                super.scale(scale, originX, originY);
    27462668                rebuild(true);
    27472669        }
    27482670
    2749        
    2750         protected Rectangle getPixelBounds(TextLayout layout)
    2751         {
     2671        protected Rectangle getPixelBounds(TextLayout layout) {
    27522672                // Does 'layout' need to be synchronized (similar to _textLayouts below)??
    27532673                int x = getX();
    27542674                int y = getY();
    27552675
    2756                 int ldx = 1+x+getJustOffset(layout); // Layout draw x                           
     2676                int ldx = 1 + x + getJustOffset(layout); // Layout draw x
    27572677                Rectangle layout_rect = layout.getPixelBounds(null, ldx, y);
    27582678
    2759                 return layout_rect;             
    2760         }
    2761        
    2762        
    2763         public Rectangle getPixelBoundsUnion()
    2764         {
    2765                 synchronized (_textLayouts) {
    2766                        
    2767                         int x = getX();
    2768                         int y = getY();
    2769        
    2770                         int min_xl = Integer.MAX_VALUE;
    2771                         int max_xr = Integer.MIN_VALUE;
    2772        
    2773                         int min_yt = Integer.MAX_VALUE;
    2774                         int max_yb = Integer.MIN_VALUE;
    2775                
    2776                        
    2777                         for (int i = 0; i < _textLayouts.size(); i++) {
    2778                                 TextLayout layout = _textLayouts.get(i);
    2779 
    2780                                 int ldx = 1+x+getJustOffset(layout); // Layout draw x                           
    2781                                 Rectangle layout_rect = layout.getPixelBounds(null, ldx, y);
    2782                                        
    2783                                 int xl = layout_rect.x;
    2784                                 int xr = xl + layout_rect.width -1;
    2785                                
    2786                                 int yt = layout_rect.y;
    2787                                 int yb = yt + layout_rect.height -1;
    2788                                
    2789                                 min_xl = Math.min(min_xl,xl);
    2790                                 max_xr = Math.max(max_xr,xr);
    2791                                
    2792                                 min_yt = Math.min(min_yt,yt);
    2793                                 max_yb = Math.max(max_yb,yb);
    2794                         }
    2795                        
    2796                         if ((min_xl >= max_xr) || (min_yt >= max_yb)) {
    2797                                 // No valid rectangle are found
    2798                                 return null;
    2799                         }
    2800                        
    2801                         return new Rectangle(min_xl,min_yt,max_xr-min_xl+1,max_yb-min_yt+1);
    2802                        
    2803                 }
    2804                                        
    2805         }
     2679                return layout_rect;
     2680        }
     2681
     2682        /**
     2683         * Creates the smallest possible rectangle object to enclose the Text Item
     2684         * completely. Width of the rectangle is determined by the line in the Text Item
     2685         * that protrudes to the right the most. Height of the rectangle is determined
     2686         * by the number of lines in the Text Item.
     2687         *
     2688         * @return A rectangle enclosing the Text Item, without gravity represented.
     2689         * @see #getPixelBoundsUnionTight()
     2690         */
     2691        public Rectangle getPixelBoundsUnion() {
     2692                final Rectangle rect = getPixelBounds(_textLayouts.get(0));
     2693
     2694                int cumulativeHeight = rect.height;
     2695                int maxWidth = rect.width;
     2696
     2697                if (_textLayouts.size() > 1) {
     2698                        for (int i = 1; i < _textLayouts.size(); i++) {
     2699                                final Rectangle r = getPixelBounds(_textLayouts.get(i));
     2700                                cumulativeHeight += _textLayouts.get(i).getDescent() + _textLayouts.get(i).getAscent();
     2701                                if (r.width > maxWidth)
     2702                                        maxWidth = r.width;
     2703                        }
     2704                }
     2705
     2706                rect.setSize(maxWidth, cumulativeHeight);
     2707
     2708                return rect;
     2709        }
     2710
     2711        /**
     2712         * Creates the smallest possible polygon to enclose the Text Item completely.
     2713         * The shape of the polygon is determined by the length of each line, tightly
     2714         * fitting the shape so that no white space is inside the resulting polygon.
     2715         *
     2716         * @return A polygon enclosing the Text Item, without gravity represented.
     2717         * @see #getPixelBoundsUnion()
     2718         */
     2719        public Polygon getPixelBoundsUnionTight() {
     2720                final Rectangle rect = getPixelBounds(_textLayouts.get(0));
     2721                if (_textLayouts.size() == 1) {
     2722                        int x = (int) rect.getX();
     2723                        int y = (int) rect.getY();
     2724                        return new Polygon(new int[] { x, x + rect.width, x + rect.width, x },
     2725                                        new int[] { y, y, y + rect.height, y + rect.height }, 4);
     2726                } else {
     2727                        final Polygon poly = new Polygon();
     2728                        poly.addPoint(rect.x, rect.y);
     2729                        poly.addPoint(rect.x + rect.width, rect.y);
     2730                        poly.addPoint(rect.x + rect.width, Math.round(rect.y + rect.height + _textLayouts.get(0).getDescent()));
     2731                        int y = (int) (rect.y + rect.height + _textLayouts.get(0).getDescent());
     2732                        for (int i = 1; i < _textLayouts.size(); i++) {
     2733                                final Rectangle r = getPixelBounds(_textLayouts.get(i));
     2734                                poly.addPoint(r.x + r.width, y);
     2735                                poly.addPoint(r.x + r.width, Math.round(y + r.height + _textLayouts.get(i).getDescent()));
     2736                                y = Math.round(y + r.height + _textLayouts.get(i).getDescent());
     2737                        }
     2738                        poly.addPoint(rect.x + getPixelBounds(_textLayouts.get(_textLayouts.size() - 1)).width, Math.round(y + _textLayouts.get(_textLayouts.size() - 1).getDescent()));
     2739                        poly.addPoint(rect.x, Math.round(y + _textLayouts.get(_textLayouts.size() - 1).getDescent()));
     2740                        return poly;
     2741                }
     2742        }
     2743
     2744        // public Rectangle getPixelBoundsUnion()
     2745        // {
     2746        // synchronized (_textLayouts) {
     2747        //
     2748        // int x = getX();
     2749        // int y = getY();
     2750        //
     2751        // int min_xl = Integer.MAX_VALUE;
     2752        // int max_xr = Integer.MIN_VALUE;
     2753        //
     2754        // int min_yt = Integer.MAX_VALUE;
     2755        // int max_yb = Integer.MIN_VALUE;
     2756        //
     2757        //
     2758        // for (int i = 0; i < _textLayouts.size(); i++) {
     2759        // TextLayout layout = _textLayouts.get(i);
     2760        //
     2761        // int ldx = 1+x+getJustOffset(layout); // Layout draw x
     2762        // Rectangle layout_rect = layout.getPixelBounds(null, ldx, y);
     2763        //
     2764        // int xl = layout_rect.x;
     2765        // int xr = xl + layout_rect.width -1;
     2766        //
     2767        // int yt = layout_rect.y;
     2768        // int yb = yt + layout_rect.height -1;
     2769        //
     2770        // min_xl = Math.min(min_xl,xl);
     2771        // max_xr = Math.max(max_xr,xr);
     2772        //
     2773        // min_yt = Math.min(min_yt,yt);
     2774        // max_yb = Math.max(max_yb,yb);
     2775        // }
     2776        //
     2777        // if ((min_xl >= max_xr) || (min_yt >= max_yb)) {
     2778        // // No valid rectangle are found
     2779        // return null;
     2780        // }
     2781        //
     2782        // return new Rectangle(min_xl,min_yt,max_xr-min_xl+1,max_yb-min_yt+1);
     2783        //
     2784        // }
     2785        //
     2786        // }
    28062787        /*
    28072788         * Returns the SIMPLE statement contained by this text item.
     
    28112792                return getText().split("\\s+")[0];
    28122793        }
    2813        
     2794
    28142795        public boolean getAutoWrap() {
    28152796                return _autoWrap;
    28162797        }
    2817        
    2818         // workaround since true is the default value and would not be displayed normally
     2798
     2799        // workaround since true is the default value and would not be displayed
     2800        // normally
    28192801        public String getAutoWrapToSave() {
    2820                 if(!_autoWrap) {
     2802                if (!_autoWrap) {
    28212803                        return null;
    28222804                }
    28232805                return "true";
    28242806        }
    2825        
     2807
    28262808        public void setAutoWrap(boolean autoWrap) {
    28272809                _autoWrap = autoWrap;
Note: See TracChangeset for help on using the changeset viewer.