Search in sources :

Example 16 with FontMetrics

use of java.awt.FontMetrics in project processing by processing.

the class Toolkit method setMenuMnemonics.

/**
   * Removes all mnemonics, then sets a mnemonic for each menu and menu item
   * recursively by these rules:
   * <ol>
   * <li> It tries to assign one of <a href="http://techbase.kde.org/Projects/Usability/HIG/Keyboard_Accelerators">
   * KDE's defaults</a>.</li>
   * <li> Failing that, it loops through the first letter of each word, where a word
   *  is a block of Unicode "alphabetical" chars, looking for an upper-case ASCII mnemonic
   *  that is not taken. This is to try to be relevant, by using a letter well-associated
   *  with the command. (MS guidelines) </li>
   * <li> Ditto, but with lowercase. </li>
   * <li> Next, it tries the second ASCII character, if its width &gt;= half the width of
   *  'A'. </li>
   * <li> If the first letters are all taken/non-ASCII, then it loops through the
   *  ASCII letters in the item, widest to narrowest, seeing if any of them is not taken.
   *  To improve readability, it discriminates against decenders (qypgj), imagining they
   *  have 2/3 their actual width. (MS guidelines: avoid decenders). It also discriminates
   *  against vowels, imagining they have 2/3 their actual width. (MS and Gnome guidelines:
   *  avoid vowels.) </li>
   * <li>Failing that, it will loop left-to-right for an available digit. This is a last
   *  resort because the normal setMnemonic dislikes them.</li>
   * <li> If that doesn't work, it doesn't assign a mnemonic. </li>
   * </ol>
   *
   * As a special case, strings starting "sketchbook → " have that bit ignored
   * because otherwise the Recent menu looks awful. However, the name <tt>"sketchbook →
   * Sketch"</tt>, for example, will have the 'S' of "Sketch" chosen, but the 's' of 'sketchbook
   * will get underlined.
   * No letter by an underscore will be assigned.
   * Disabled on Mac, per Apple guidelines.
   * <tt>menu</tt> may contain nulls.
   *
   * Author: George Bateman. Initial work Myer Nore.
   * @param menu
   *          A menu, a list of menus or an array of menu items to set mnemonics for.
   */
public static void setMenuMnemonics(JMenuItem... menu) {
    if (Platform.isMacOS())
        return;
    if (menu.length == 0)
        return;
    // The English is http://techbase.kde.org/Projects/Usability/HIG/Keyboard_Accelerators,
    // made lowercase.
    // Nothing but [a-z] except for '&' before mnemonics and regexes for changable text.
    final String[] kdePreDefStrs = { "&file", "&new", "&open", "open&recent", "&save", "save&as", "saveacop&y", "saveas&template", "savea&ll", "reloa&d", "&print", "printpre&view", "&import", "e&xport", "&closefile", "clos&eallfiles", "&quit", "&edit", "&undo", "re&do", "cu&t", "&copy", "&paste", "&delete", "select&all", "dese&lect", "&find", "find&next", "findpre&vious", "&replace", "&gotoline", "&view", "&newview", "close&allviews", "&splitview", "&removeview", "splitter&orientation", "&horizontal", "&vertical", "view&mode", "&fullscreenmode", "&zoom", "zoom&in", "zoom&out", "zoomtopage&width", "zoomwhole&page", "zoom&factor", "&insert", "&format", "&go", "&up", "&back", "&forward", "&home", "&go", "&previouspage", "&nextpage", "&firstpage", "&lastpage", "read&updocument", "read&downdocument", "&back", "&forward", "&gotopage", "&bookmarks", "&addbookmark", "bookmark&tabsasfolder", "&editbookmarks", "&newbookmarksfolder", "&tools", "&settings", "&toolbars", "configure&shortcuts", "configuretool&bars", "&configure.*", "&help", ".+&handbook", "&whatsthis", "report&bug", "&aboutprocessing", "about&kde", // de
    "&beenden", // de
    "&suchen", // Preferências; pt
    "&preferncias", // Preferências; pt
    "&sair", // fr
    "&rechercher" };
    Pattern[] kdePreDefPats = new Pattern[kdePreDefStrs.length];
    for (int i = 0; i < kdePreDefStrs.length; i++) {
        kdePreDefPats[i] = Pattern.compile(kdePreDefStrs[i].replace("&", ""));
    }
    final Pattern nonAAlpha = Pattern.compile("[^A-Za-z]");
    FontMetrics fmTmp = null;
    for (JMenuItem m : menu) {
        if (m != null) {
            fmTmp = m.getFontMetrics(m.getFont());
            break;
        }
    }
    // All null menuitems; would fail.
    if (fmTmp == null)
        return;
    // Hack for accessing variable in comparator.
    final FontMetrics fm = fmTmp;
    final Comparator<Character> charComparator = new Comparator<Character>() {

        char[] baddies = "qypgjaeiouQAEIOU".toCharArray();

        public int compare(Character ch1, Character ch2) {
            // Discriminates against descenders for readability, per MS
            // Human Interface Guide, and vowels per MS and Gnome.
            float w1 = fm.charWidth(ch1), w2 = fm.charWidth(ch2);
            for (char bad : baddies) {
                if (bad == ch1)
                    w1 *= 0.66f;
                if (bad == ch2)
                    w2 *= 0.66f;
            }
            return (int) Math.signum(w2 - w1);
        }
    };
    // Holds only [0-9a-z], not uppercase.
    // Prevents X != x, so "Save" and "Save As" aren't both given 'a'.
    final List<Character> taken = new ArrayList<Character>(menu.length);
    char firstChar;
    char[] cleanChars;
    Character[] cleanCharas;
    // METHOD 1: attempt to assign KDE defaults.
    for (JMenuItem jmi : menu) {
        if (jmi == null)
            continue;
        if (jmi.getText() == null)
            continue;
        // Reset all mnemonics.
        jmi.setMnemonic(0);
        String asciiName = nonAAlpha.matcher(jmi.getText()).replaceAll("");
        String lAsciiName = asciiName.toLowerCase();
        for (int i = 0; i < kdePreDefStrs.length; i++) {
            if (kdePreDefPats[i].matcher(lAsciiName).matches()) {
                char mnem = asciiName.charAt(kdePreDefStrs[i].indexOf("&"));
                jmi.setMnemonic(mnem);
                jmi.setDisplayedMnemonicIndex(jmi.getText().indexOf(mnem));
                // to lowercase
                taken.add((char) (mnem | 32));
                break;
            }
        }
    }
    // Where KDE defaults fail, use an algorithm.
    algorithmicAssignment: for (JMenuItem jmi : menu) {
        if (jmi == null)
            continue;
        if (jmi.getText() == null)
            continue;
        // Already assigned.
        if (jmi.getMnemonic() != 0)
            continue;
        // The string can't be made lower-case as that would spoil
        // the width comparison.
        String cleanString = jmi.getText();
        if (cleanString.startsWith("sketchbook → "))
            cleanString = cleanString.substring(13);
        if (cleanString.length() == 0)
            continue;
        // First, ban letters by underscores.
        final List<Character> banned = new ArrayList<Character>();
        for (int i = 0; i < cleanString.length(); i++) {
            if (cleanString.charAt(i) == '_') {
                if (i > 0)
                    banned.add(Character.toLowerCase(cleanString.charAt(i - 1)));
                if (i + 1 < cleanString.length())
                    banned.add(Character.toLowerCase(cleanString.charAt(i + 1)));
            }
        }
        // because there could be non-ASCII letters in a word.
        for (String wd : cleanString.split("[^\\p{IsAlphabetic}]")) {
            if (wd.length() == 0)
                continue;
            firstChar = wd.charAt(0);
            if (taken.contains(Character.toLowerCase(firstChar)))
                continue;
            if (banned.contains(Character.toLowerCase(firstChar)))
                continue;
            if ('A' <= firstChar && firstChar <= 'Z') {
                jmi.setMnemonic(firstChar);
                jmi.setDisplayedMnemonicIndex(jmi.getText().indexOf(firstChar));
                // tolowercase
                taken.add((char) (firstChar | 32));
                continue algorithmicAssignment;
            }
        }
        // METHOD 3: Lowercase starts of words.
        for (String wd : cleanString.split("[^\\p{IsAlphabetic}]")) {
            if (wd.length() == 0)
                continue;
            firstChar = wd.charAt(0);
            if (taken.contains(Character.toLowerCase(firstChar)))
                continue;
            if (banned.contains(Character.toLowerCase(firstChar)))
                continue;
            if ('a' <= firstChar && firstChar <= 'z') {
                jmi.setMnemonic(firstChar);
                jmi.setDisplayedMnemonicIndex(jmi.getText().indexOf(firstChar));
                // is lowercase
                taken.add(firstChar);
                continue algorithmicAssignment;
            }
        }
        // METHOD 4: Second wide-enough ASCII letter.
        cleanString = nonAAlpha.matcher(jmi.getText()).replaceAll("");
        if (cleanString.length() >= 2) {
            char ascii2nd = cleanString.charAt(1);
            if (!taken.contains((char) (ascii2nd | 32)) && !banned.contains((char) (ascii2nd | 32)) && fm.charWidth('A') <= 2 * fm.charWidth(ascii2nd)) {
                jmi.setMnemonic(ascii2nd);
                jmi.setDisplayedMnemonicIndex(jmi.getText().indexOf(ascii2nd));
                taken.add((char) (ascii2nd | 32));
                continue algorithmicAssignment;
            }
        }
        // METHOD 5: charComparator over all ASCII letters.
        cleanChars = cleanString.toCharArray();
        cleanCharas = new Character[cleanChars.length];
        for (int i = 0; i < cleanChars.length; i++) {
            cleanCharas[i] = new Character(cleanChars[i]);
        }
        // sorts in increasing order
        Arrays.sort(cleanCharas, charComparator);
        for (char mnem : cleanCharas) {
            if (taken.contains(Character.toLowerCase(mnem)))
                continue;
            if (banned.contains(Character.toLowerCase(mnem)))
                continue;
            // NB: setMnemonic(char) doesn't want [^A-Za-z]
            jmi.setMnemonic(mnem);
            jmi.setDisplayedMnemonicIndex(jmi.getText().indexOf(mnem));
            taken.add(Character.toLowerCase(mnem));
            continue algorithmicAssignment;
        }
        // METHOD 6: Digits as last resort.
        for (char digit : jmi.getText().replaceAll("[^0-9]", "").toCharArray()) {
            if (taken.contains(digit))
                continue;
            if (banned.contains(digit))
                continue;
            jmi.setMnemonic(KeyEvent.VK_0 + digit - '0');
            // setDisplayedMnemonicIndex() unneeded: no case issues.
            taken.add(digit);
            continue algorithmicAssignment;
        }
    }
    // Finally, RECURSION.
    for (JMenuItem jmi : menu) {
        if (jmi instanceof JMenu)
            setMenuMnemsInside((JMenu) jmi);
    }
}
Also used : Pattern(java.util.regex.Pattern) ArrayList(java.util.ArrayList) Comparator(java.util.Comparator) FontMetrics(java.awt.FontMetrics) StringList(processing.data.StringList) List(java.util.List) ArrayList(java.util.ArrayList) JMenuItem(javax.swing.JMenuItem) JMenu(javax.swing.JMenu)

Example 17 with FontMetrics

use of java.awt.FontMetrics in project processing by processing.

the class BufferedStyledDocument method updateMode.

/**
   * Change coloring, fonts, etc in response to a mode change.
   */
protected void updateMode() {
    Mode mode = editor.getMode();
    // necessary?
    MutableAttributeSet standard = new SimpleAttributeSet();
    StyleConstants.setAlignment(standard, StyleConstants.ALIGN_LEFT);
    consoleDoc.setParagraphAttributes(0, 0, standard, true);
    Font font = Preferences.getFont("console.font");
    // build styles for different types of console output
    Color bgColor = mode.getColor("console.color");
    Color fgColorOut = mode.getColor("console.output.color");
    Color fgColorErr = mode.getColor("console.error.color");
    // Make things line up with the Editor above. If this is ever removed,
    // setBorder(null) should be called instead. The defaults are nasty.
    setBorder(new MatteBorder(0, Editor.LEFT_GUTTER, 0, 0, bgColor));
    stdStyle = new SimpleAttributeSet();
    StyleConstants.setForeground(stdStyle, fgColorOut);
    StyleConstants.setBackground(stdStyle, bgColor);
    StyleConstants.setFontSize(stdStyle, font.getSize());
    StyleConstants.setFontFamily(stdStyle, font.getFamily());
    StyleConstants.setBold(stdStyle, font.isBold());
    StyleConstants.setItalic(stdStyle, font.isItalic());
    errStyle = new SimpleAttributeSet();
    StyleConstants.setForeground(errStyle, fgColorErr);
    StyleConstants.setBackground(errStyle, bgColor);
    StyleConstants.setFontSize(errStyle, font.getSize());
    StyleConstants.setFontFamily(errStyle, font.getFamily());
    StyleConstants.setBold(errStyle, font.isBold());
    StyleConstants.setItalic(errStyle, font.isItalic());
    if (UIManager.getLookAndFeel().getID().equals("Nimbus")) {
        getViewport().setBackground(bgColor);
        consoleTextPane.setOpaque(false);
        consoleTextPane.setBackground(new Color(0, 0, 0, 0));
    } else {
        consoleTextPane.setBackground(bgColor);
    }
    // calculate height of a line of text in pixels
    // and size window accordingly
    FontMetrics metrics = this.getFontMetrics(font);
    int height = metrics.getAscent() + metrics.getDescent();
    //, 4);
    int lines = Preferences.getInteger("console.lines");
    //10; // unclear why this is necessary, but it is
    int sizeFudge = 6;
    setPreferredSize(new Dimension(1024, (height * lines) + sizeFudge));
    setMinimumSize(new Dimension(1024, (height * 4) + sizeFudge));
}
Also used : MatteBorder(javax.swing.border.MatteBorder) FontMetrics(java.awt.FontMetrics) Mode(processing.app.Mode) Color(java.awt.Color) Dimension(java.awt.Dimension) Font(java.awt.Font)

Example 18 with FontMetrics

use of java.awt.FontMetrics in project processing by processing.

the class CompositionTextManager method getCaretLocation.

private Point getCaretLocation() {
    Point loc = new Point();
    TextAreaPainter painter = textArea.getPainter();
    FontMetrics fm = painter.getFontMetrics();
    int offsetY = fm.getHeight() - COMPOSING_UNDERBAR_HEIGHT;
    int lineIndex = textArea.getCaretLine();
    loc.y = lineIndex * fm.getHeight() + offsetY;
    int offsetX = textArea.getCaretPosition() - textArea.getLineStartOffset(lineIndex);
    loc.x = textArea.offsetToX(lineIndex, offsetX);
    return loc;
}
Also used : TextAreaPainter(processing.app.syntax.TextAreaPainter) FontMetrics(java.awt.FontMetrics) Point(java.awt.Point) Point(java.awt.Point)

Example 19 with FontMetrics

use of java.awt.FontMetrics in project processing by processing.

the class CompletionPanel method calcWidth.

private int calcWidth() {
    int maxWidth = 300;
    float min = 0;
    FontMetrics fm = textarea.getGraphics().getFontMetrics();
    for (int i = 0; i < completionList.getModel().getSize(); i++) {
        float h = fm.stringWidth(completionList.getModel().getElementAt(i).getLabel());
        min = Math.max(min, h);
    }
    int w = Math.min((int) min, maxWidth);
    horizontalScrollBarVisible = (w == maxWidth);
    // add icon width too!
    w += classIcon.getIconWidth();
    // a bit of offset
    w += fm.stringWidth("           ");
    // popup menu width
    return w;
}
Also used : FontMetrics(java.awt.FontMetrics) Point(java.awt.Point)

Example 20 with FontMetrics

use of java.awt.FontMetrics in project processing by processing.

the class PJOGL method getTextWidth.

@Override
protected int getTextWidth(Object font, char[] buffer, int start, int stop) {
    // maybe should use one of the newer/fancier functions for this?
    int length = stop - start;
    FontMetrics metrics = getFontMetrics((Font) font);
    return metrics.charsWidth(buffer, start, length);
}
Also used : FontMetrics(java.awt.FontMetrics)

Aggregations

FontMetrics (java.awt.FontMetrics)116 Font (java.awt.Font)43 Graphics2D (java.awt.Graphics2D)32 Point (java.awt.Point)29 Dimension (java.awt.Dimension)21 Rectangle2D (java.awt.geom.Rectangle2D)20 Color (java.awt.Color)18 Insets (java.awt.Insets)18 Rectangle (java.awt.Rectangle)17 GradientPaint (java.awt.GradientPaint)9 BufferedImage (java.awt.image.BufferedImage)9 Graphics (java.awt.Graphics)8 BasicStroke (java.awt.BasicStroke)6 Shape (java.awt.Shape)5 JLabel (javax.swing.JLabel)5 Canvas (java.awt.Canvas)4 BadLocationException (javax.swing.text.BadLocationException)4 Polygon (java.awt.Polygon)3 FontRenderContext (java.awt.font.FontRenderContext)3 ArrayList (java.util.ArrayList)3