//# 1 errors, 174 messages
//#
/*
    //#UIUtilities.java:1:1: class: com.dmdirc.addons.ui_swing.UIUtilities
 * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.dmdirc.addons.ui_swing;

import com.dmdirc.logger.ErrorLevel;
import com.dmdirc.logger.Logger;
import com.dmdirc.addons.ui_swing.actions.RedoAction;
import com.dmdirc.addons.ui_swing.actions.UndoAction;
import com.dmdirc.addons.ui_swing.components.DMDircUndoableEditListener;
import com.dmdirc.util.ReturnableThread;

import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.event.KeyEvent;
import java.lang.reflect.InvocationTargetException;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.JTextComponent;
import javax.swing.undo.UndoManager;

import net.miginfocom.layout.PlatformDefaults;

/**
 * UI constants.
 */
public final class UIUtilities {

    /** Size of a large border. */
    public static final int LARGE_BORDER = 10;
    /** Size of a small border. */
    public static final int SMALL_BORDER = 5;
    /** Standard button size. */
    public static final Dimension BUTTON_SIZE = new Dimension(100, 25);
    //#UIUtilities.java:59: method: com.dmdirc.addons.ui_swing.UIUtilities.com.dmdirc.addons.ui_swing.UIUtilities__static_init
    //#output(com.dmdirc.addons.ui_swing.UIUtilities__static_init): BUTTON_SIZE
    //#output(com.dmdirc.addons.ui_swing.UIUtilities__static_init): __Descendant_Table[com/dmdirc/addons/ui_swing/UIUtilities]
    //#output(com.dmdirc.addons.ui_swing.UIUtilities__static_init): new Dimension(UIUtilities__static_init#1) num objects
    //#new obj(com.dmdirc.addons.ui_swing.UIUtilities__static_init): new Dimension(UIUtilities__static_init#1)
    //#post(com.dmdirc.addons.ui_swing.UIUtilities__static_init): BUTTON_SIZE == &new Dimension(UIUtilities__static_init#1)
    //#post(com.dmdirc.addons.ui_swing.UIUtilities__static_init): __Descendant_Table[com/dmdirc/addons/ui_swing/UIUtilities] == &__Dispatch_Table
    //#post(com.dmdirc.addons.ui_swing.UIUtilities__static_init): new Dimension(UIUtilities__static_init#1) num objects == 1
    //#UIUtilities.java:59: end of method: com.dmdirc.addons.ui_swing.UIUtilities.com.dmdirc.addons.ui_swing.UIUtilities__static_init

    /** Not intended to be instatiated. */
    private UIUtilities() {
    //#UIUtilities.java:62: method: void com.dmdirc.addons.ui_swing.UIUtilities.com.dmdirc.addons.ui_swing.UIUtilities()
    }
    //#UIUtilities.java:63: end of method: void com.dmdirc.addons.ui_swing.UIUtilities.com.dmdirc.addons.ui_swing.UIUtilities()

    /**
     * Adds an undo manager and associated key bindings to the specified text
     * component.
     * 
     * @param component component Text component to add an undo manager to
     */
    public static void addUndoManager(final JTextComponent component) {
        final UndoManager undoManager = new UndoManager();
    //#UIUtilities.java:72: method: void com.dmdirc.addons.ui_swing.UIUtilities.addUndoManager(JTextComponent)
    //#input(void addUndoManager(JTextComponent)): component
    //#pre[1] (void addUndoManager(JTextComponent)): component != null
    //#presumption(void addUndoManager(JTextComponent)): javax.swing.text.JTextComponent:getActionMap(...)@79 != null
    //#presumption(void addUndoManager(JTextComponent)): javax.swing.text.JTextComponent:getActionMap(...)@85 != null
    //#presumption(void addUndoManager(JTextComponent)): javax.swing.text.JTextComponent:getDocument(...)@75 != null
    //#presumption(void addUndoManager(JTextComponent)): javax.swing.text.JTextComponent:getInputMap(...)@82 != null
    //#presumption(void addUndoManager(JTextComponent)): javax.swing.text.JTextComponent:getInputMap(...)@88 != null
    //#unanalyzed(void addUndoManager(JTextComponent)): Effects-of-calling:javax.swing.AbstractAction

        // Listen for undo and redo events
        component.getDocument().addUndoableEditListener(
                new DMDircUndoableEditListener(undoManager));

        // Create an undo action and add it to the text component
        component.getActionMap().put("Undo", new UndoAction(undoManager));

        // Bind the undo action to ctl-Z
        component.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo");

        // Create a redo action and add it to the text component
        component.getActionMap().put("Redo", new RedoAction(undoManager));

        // Bind the redo action to ctl-Y
        component.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo");
    }
    //#UIUtilities.java:89: end of method: void com.dmdirc.addons.ui_swing.UIUtilities.addUndoManager(JTextComponent)

    /**
     * Initialises any settings required by this UI (this is always called
     * before any aspect of the UI is instansiated).
     *
     * @throws UnsupportedOperationException If unable to switch to the system
     * look and feel
     */
    public static void initUISettings() {

        try {

            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    //#UIUtilities.java:102: method: void com.dmdirc.addons.ui_swing.UIUtilities.initUISettings()
    //#presumption(void initUISettings()): (int) (net.miginfocom.layout.UnitValue:getValue(...)@130) in {-2_147_483_648..4_294_967_295}
    //#presumption(void initUISettings()): net.miginfocom.layout.PlatformDefaults:getPanelInsets(...)@130 != null
    //#unanalyzed(void initUISettings()): Effects-of-calling:javax.swing.UIManager:getLookAndFeel
    //#unanalyzed(void initUISettings()): Effects-of-calling:java.lang.Object:getClass
    //#unanalyzed(void initUISettings()): Effects-of-calling:java.lang.Class:getName
    //#unanalyzed(void initUISettings()): Effects-of-calling:java.lang.String:equals
    //#unanalyzed(void initUISettings()): Effects-of-calling:java.lang.System:getProperty
        } catch (InstantiationException ex) {
            throw new UnsupportedOperationException("Unable to switch to the " +
                    "system look and feel", ex);
        } catch (ClassNotFoundException ex) {
            throw new UnsupportedOperationException("Unable to switch to the " +
                    "system look and feel", ex);
        } catch (UnsupportedLookAndFeelException ex) {
            throw new UnsupportedOperationException("Unable to switch to the " +
                    "system look and feel", ex);
        } catch (IllegalAccessException ex) {
            throw new UnsupportedOperationException("Unable to switch to the " +
                    "system look and feel", ex);
        }

        UIManager.put("swing.useSystemFontSettings", true);
        if (getTabbedPaneOpaque()) {
            // If this is set on windows then .setOpaque seems to be ignored
            // and still used as true
            UIManager.put("TabbedPane.contentOpaque", false);
        }
        UIManager.put("swing.boldMetal", false);
        UIManager.put("InternalFrame.useTaskBar", false);
        UIManager.put("SplitPaneDivider.border",
                BorderFactory.createEmptyBorder());
        UIManager.put("Tree.scrollsOnExpand", true);
        UIManager.put("Tree.scrollsHorizontallyAndVertically", true);
        UIManager.put("SplitPane.border", BorderFactory.createEmptyBorder());
        UIManager.put("SplitPane.dividerSize", (int) PlatformDefaults.getPanelInsets(0).getValue());
    //#UIUtilities.java:130: Warning: method not available - call not analyzed
    //#    call on UnitValue net.miginfocom.layout.PlatformDefaults:getPanelInsets(int)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: void initUISettings()
    //#    unanalyzed callee: UnitValue net.miginfocom.layout.PlatformDefaults:getPanelInsets(int)
    //#UIUtilities.java:130: Warning: method not available - call not analyzed
    //#    call on float net.miginfocom.layout.UnitValue:getValue()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: void initUISettings()
    //#    unanalyzed callee: float net.miginfocom.layout.UnitValue:getValue()
        UIManager.put("TreeUI", "javax.swing.plaf.metal.MetalTreeUI");
        PlatformDefaults.setDefaultRowAlignmentBaseline(false);
    //#UIUtilities.java:132: Warning: method not available - call not analyzed
    //#    call on void net.miginfocom.layout.PlatformDefaults:setDefaultRowAlignmentBaseline(bool)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: void initUISettings()
    //#    unanalyzed callee: void net.miginfocom.layout.PlatformDefaults:setDefaultRowAlignmentBaseline(bool)
    }
    //#UIUtilities.java:133: end of method: void com.dmdirc.addons.ui_swing.UIUtilities.initUISettings()

    /**
     * Returns the class name of the look and feel from its display name.
     *
     * @param displayName Look and feel display name
     *
     * @return Look and feel class name or a zero length string
     */
    public static String getLookAndFeel(final String displayName) {
        if (displayName == null || displayName.isEmpty() ||
    //#UIUtilities.java:143: method: String com.dmdirc.addons.ui_swing.UIUtilities.getLookAndFeel(String)
    //#input(String getLookAndFeel(String)): displayName
    //#output(String getLookAndFeel(String)): java.lang.StringBuilder:toString(...)._tainted
    //#output(String getLookAndFeel(String)): return_value
    //#new obj(String getLookAndFeel(String)): java.lang.StringBuilder:toString(...)
    //#presumption(String getLookAndFeel(String)): arr$.length@150 <= 4_294_967_295
    //#presumption(String getLookAndFeel(String)): arr$[i$]@150 != null
    //#presumption(String getLookAndFeel(String)): javax.swing.UIManager:getInstalledLookAndFeels(...)@150 != null
    //#presumption(String getLookAndFeel(String)): javax.swing.UIManager_LookAndFeelInfo:getName(...)@151 != null
    //#post(String getLookAndFeel(String)): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(String getLookAndFeel(String)): init'ed(return_value)
    //#test_vector(String getLookAndFeel(String)): displayName: Addr_Set{null}, Inverse{null}
    //#test_vector(String getLookAndFeel(String)): java.lang.String:equals(...)@143: {0}, {1}
    //#test_vector(String getLookAndFeel(String)): java.lang.String:equals(...)@151: {0}, {1}
    //#test_vector(String getLookAndFeel(String)): java.lang.String:isEmpty(...)@143: {1}, {0}
    //#test_vector(String getLookAndFeel(String)): java.lang.StringBuilder:length(...)@157: {-2_147_483_648..-1, 1..4_294_967_295}, {0}
                "Native".equals(displayName)) {
            return UIManager.getSystemLookAndFeelClassName();
        }

        final StringBuilder classNameBuilder = new StringBuilder();

        for (LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
            if (laf.getName().equals(displayName)) {
                classNameBuilder.append(laf.getClassName());
                break;
            }
        }

        if (classNameBuilder.length() == 0) {
            classNameBuilder.append(UIManager.getSystemLookAndFeelClassName());
        }

        return classNameBuilder.toString();
    //#UIUtilities.java:161: end of method: String com.dmdirc.addons.ui_swing.UIUtilities.getLookAndFeel(String)
    }

    /**
     * Invokes and waits for the specified runnable, executed on the EDT.
     * 
     * @param runnable Thread to be executed
     */
    public static void invokeAndWait(final Runnable runnable) {
        if (SwingUtilities.isEventDispatchThread()) {
    //#UIUtilities.java:170: method: void com.dmdirc.addons.ui_swing.UIUtilities.invokeAndWait(Runnable)
    //#input(void invokeAndWait(Runnable)): com.dmdirc.logger.ErrorLevel.HIGH
    //#input(void invokeAndWait(Runnable)): runnable
    //#pre[1] (void invokeAndWait(Runnable)): (soft) runnable != null
    //#presumption(void invokeAndWait(Runnable)): init'ed(com.dmdirc.logger.ErrorLevel.HIGH)
    //#test_vector(void invokeAndWait(Runnable)): javax.swing.SwingUtilities:isEventDispatchThread(...)@170: {0}, {1}
            runnable.run();
        } else {
            try {
                SwingUtilities.invokeAndWait(runnable);
            } catch (InterruptedException ex) {
            //Ignore
            } catch (InvocationTargetException ex) {
                Logger.appError(ErrorLevel.HIGH, "Unable to execute thread.", ex);
    //#UIUtilities.java:178: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: void invokeAndWait(Runnable)
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
            }
        }
    }
    //#UIUtilities.java:181: end of method: void com.dmdirc.addons.ui_swing.UIUtilities.invokeAndWait(Runnable)

    /**
     * Invokes and waits for the specified runnable, executed on the EDT.
     * 
     * @param <T> The return type of the returnable thread
     * @param returnable Thread to be executed
     * @return Result from the compelted thread
     */
    public static <T> T invokeAndWait(final ReturnableThread<T> returnable) {
        if (SwingUtilities.isEventDispatchThread()) {
    //#UIUtilities.java:191: method: Object com.dmdirc.addons.ui_swing.UIUtilities.invokeAndWait(ReturnableThread)
    //#input(Object invokeAndWait(ReturnableThread)): com.dmdirc.logger.ErrorLevel.HIGH
    //#input(Object invokeAndWait(ReturnableThread)): returnable
    //#output(Object invokeAndWait(ReturnableThread)): return_value
    //#pre[1] (Object invokeAndWait(ReturnableThread)): returnable != null
    //#presumption(Object invokeAndWait(ReturnableThread)): init'ed(com.dmdirc.logger.ErrorLevel.HIGH)
    //#post(Object invokeAndWait(ReturnableThread)): init'ed(return_value)
    //#test_vector(Object invokeAndWait(ReturnableThread)): javax.swing.SwingUtilities:isEventDispatchThread(...)@191: {0}, {1}
            returnable.run();
    //#UIUtilities.java:192: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ReturnableThread:run()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: Object invokeAndWait(ReturnableThread)
    //#    unanalyzed callee: void com.dmdirc.util.ReturnableThread:run()
        } else {
            try {
                SwingUtilities.invokeAndWait(returnable);
            } catch (InterruptedException ex) {
                //Ignore
            } catch (InvocationTargetException ex) {
                Logger.appError(ErrorLevel.HIGH, "Unable to execute thread.", ex);
    //#UIUtilities.java:199: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: Object invokeAndWait(ReturnableThread)
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
            }            
        }
        
        return returnable.getObject();
    //#UIUtilities.java:203: Warning: method not available - call not analyzed
    //#    call on Object com.dmdirc.util.ReturnableThread:getObject()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: Object invokeAndWait(ReturnableThread)
    //#    unanalyzed callee: Object com.dmdirc.util.ReturnableThread:getObject()
    //#UIUtilities.java:203: end of method: Object com.dmdirc.addons.ui_swing.UIUtilities.invokeAndWait(ReturnableThread)
    }

    /**
     * Queues the runnable to be executed on the EDT.
     * 
     * @param runnable Runnable to be executed.
     */
    public static void invokeLater(final Runnable runnable) {
        if (SwingUtilities.isEventDispatchThread()) {
    //#UIUtilities.java:212: method: void com.dmdirc.addons.ui_swing.UIUtilities.invokeLater(Runnable)
    //#input(void invokeLater(Runnable)): runnable
    //#pre[1] (void invokeLater(Runnable)): (soft) runnable != null
    //#test_vector(void invokeLater(Runnable)): javax.swing.SwingUtilities:isEventDispatchThread(...)@212: {0}, {1}
            runnable.run();
        } else {
            SwingUtilities.invokeLater(runnable);
        }
    }
    //#UIUtilities.java:217: end of method: void com.dmdirc.addons.ui_swing.UIUtilities.invokeLater(Runnable)

    /**
     * Check if we are using one of the Windows Look and Feels
     * 
     * @return True iff the current LAF is "Windows" or "Windows Classic"
     */
    public static boolean isWindowsUI() {
        final String uiname = UIManager.getLookAndFeel().getClass().getName();
    //#UIUtilities.java:225: method: bool com.dmdirc.addons.ui_swing.UIUtilities.isWindowsUI()
    //#output(bool isWindowsUI()): return_value
    //#presumption(bool isWindowsUI()): java.lang.Object:getClass(...)@225 != null
    //#presumption(bool isWindowsUI()): javax.swing.UIManager:getLookAndFeel(...)@225 != null
    //#post(bool isWindowsUI()): init'ed(return_value)
        final String windows =
    //#UIUtilities.java:226: Warning: unused assignment
    //#    Unused assignment into windows
    //#    severity: LOW
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: bool isWindowsUI()
                "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
        final String classic =
    //#UIUtilities.java:228: Warning: unused assignment
    //#    Unused assignment into classic
    //#    severity: LOW
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: bool isWindowsUI()
                "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel";

        return windows.equals(uiname) || classic.equals(uiname);
    //#UIUtilities.java:231: end of method: bool com.dmdirc.addons.ui_swing.UIUtilities.isWindowsUI()
    }

    /**
     * Get the value to pass to set Opaque on items being added to a JTabbedPane
     * 
     * @return True iff the current LAF is not Windows or OS X.
     * @since 0.6
     */
    public static boolean getTabbedPaneOpaque() {
        final String uiname = UIManager.getLookAndFeel().getClass().getName();
    //#UIUtilities.java:241: method: bool com.dmdirc.addons.ui_swing.UIUtilities.getTabbedPaneOpaque()
    //#output(bool getTabbedPaneOpaque()): return_value
    //#presumption(bool getTabbedPaneOpaque()): java.lang.Object:getClass(...)@241 != null
    //#presumption(bool getTabbedPaneOpaque()): javax.swing.UIManager:getLookAndFeel(...)@241 != null
    //#post(bool getTabbedPaneOpaque()): init'ed(return_value)
    //#unanalyzed(bool getTabbedPaneOpaque()): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(bool getTabbedPaneOpaque()): Effects-of-calling:javax.swing.UIManager:getLookAndFeel
    //#unanalyzed(bool getTabbedPaneOpaque()): Effects-of-calling:java.lang.Object:getClass
    //#unanalyzed(bool getTabbedPaneOpaque()): Effects-of-calling:java.lang.Class:getName
    //#unanalyzed(bool getTabbedPaneOpaque()): Effects-of-calling:java.lang.String:equals
        final String windows =
    //#UIUtilities.java:242: Warning: unused assignment
    //#    Unused assignment into windows
    //#    severity: LOW
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: bool getTabbedPaneOpaque()
                "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
        final String nimbus = "sun.swing.plaf.nimbus.NimbusLookAndFeel";
    //#UIUtilities.java:244: Warning: unused assignment
    //#    Unused assignment into nimbus
    //#    severity: LOW
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: bool getTabbedPaneOpaque()

        return !(windows.equals(uiname) || Apple.isAppleUI() || nimbus.equals(
    //#UIUtilities.java:246: end of method: bool com.dmdirc.addons.ui_swing.UIUtilities.getTabbedPaneOpaque()
                uiname));
    }
    
    /**
     * Get the DOWN_MASK for the command/ctrl key.
     * 
     * @return on OSX this returns META_DOWN_MASK, else CTRL_DOWN_MASK
     * @since 0.6
     */
    public static int getCtrlDownMask() {
        return Apple.isAppleUI() ? KeyEvent.META_DOWN_MASK : KeyEvent.CTRL_DOWN_MASK;
    //#UIUtilities.java:257: method: int com.dmdirc.addons.ui_swing.UIUtilities.getCtrlDownMask()
    //#output(int getCtrlDownMask()): return_value
    //#post(int getCtrlDownMask()): return_value == One-of{256, 128}
    //#post(int getCtrlDownMask()): return_value in {128, 256}
    //#unanalyzed(int getCtrlDownMask()): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(int getCtrlDownMask()): Effects-of-calling:javax.swing.UIManager:getLookAndFeel
    //#unanalyzed(int getCtrlDownMask()): Effects-of-calling:java.lang.Object:getClass
    //#unanalyzed(int getCtrlDownMask()): Effects-of-calling:java.lang.Class:getName
    //#unanalyzed(int getCtrlDownMask()): Effects-of-calling:java.lang.String:equals
    //#UIUtilities.java:257: end of method: int com.dmdirc.addons.ui_swing.UIUtilities.getCtrlDownMask()
    }
    
    /**
     * Get the MASK for the command/ctrl key.
     * 
     * @return on OSX this returns META_MASK, else CTRL_MASK
     * @since 0.6
     */
    public static int getCtrlMask() {
        return Apple.isAppleUI() ? KeyEvent.META_MASK : KeyEvent.CTRL_MASK;
    //#UIUtilities.java:267: method: int com.dmdirc.addons.ui_swing.UIUtilities.getCtrlMask()
    //#output(int getCtrlMask()): return_value
    //#post(int getCtrlMask()): return_value == One-of{4, 2}
    //#post(int getCtrlMask()): return_value in {2, 4}
    //#unanalyzed(int getCtrlMask()): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(int getCtrlMask()): Effects-of-calling:javax.swing.UIManager:getLookAndFeel
    //#unanalyzed(int getCtrlMask()): Effects-of-calling:java.lang.Object:getClass
    //#unanalyzed(int getCtrlMask()): Effects-of-calling:java.lang.Class:getName
    //#unanalyzed(int getCtrlMask()): Effects-of-calling:java.lang.String:equals
    //#UIUtilities.java:267: end of method: int com.dmdirc.addons.ui_swing.UIUtilities.getCtrlMask()
    }
    
    /**
     * Check if the command/ctrl key is pressed down.
     * 
     * @param e The KeyEvent to check
     * @return on OSX this returns e.isMetaDown(), else e.isControlDown()
     * @since 0.6
     */
    public static boolean isCtrlDown(final KeyEvent e) {
        return Apple.isAppleUI() ? e.isMetaDown() : e.isControlDown();
    //#UIUtilities.java:278: method: bool com.dmdirc.addons.ui_swing.UIUtilities.isCtrlDown(KeyEvent)
    //#input(bool isCtrlDown(KeyEvent)): e
    //#output(bool isCtrlDown(KeyEvent)): return_value
    //#pre[1] (bool isCtrlDown(KeyEvent)): e != null
    //#post(bool isCtrlDown(KeyEvent)): init'ed(return_value)
    //#unanalyzed(bool isCtrlDown(KeyEvent)): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(bool isCtrlDown(KeyEvent)): Effects-of-calling:javax.swing.UIManager:getLookAndFeel
    //#unanalyzed(bool isCtrlDown(KeyEvent)): Effects-of-calling:java.lang.Object:getClass
    //#unanalyzed(bool isCtrlDown(KeyEvent)): Effects-of-calling:java.lang.Class:getName
    //#unanalyzed(bool isCtrlDown(KeyEvent)): Effects-of-calling:java.lang.String:equals
    //#UIUtilities.java:278: end of method: bool com.dmdirc.addons.ui_swing.UIUtilities.isCtrlDown(KeyEvent)
    }
    
    /**
     * Clips a string if its longer than the specified width.
     * 
     * @param component Component containing string
     * @param string String to check
     * @param avaiableWidth Available Width
     * 
     * @return String (clipped if required)
     */
    public static String clipStringifNeeded(final JComponent component, 
            final String string, final int avaiableWidth) {
        if ((string == null) || (string.equals(""))) {
    //#UIUtilities.java:292: method: String com.dmdirc.addons.ui_swing.UIUtilities.clipStringifNeeded(JComponent, String, int)
    //#input(String clipStringifNeeded(JComponent, String, int)): "..."._tainted
    //#input(String clipStringifNeeded(JComponent, String, int)): avaiableWidth
    //#input(String clipStringifNeeded(JComponent, String, int)): component
    //#input(String clipStringifNeeded(JComponent, String, int)): string
    //#input(String clipStringifNeeded(JComponent, String, int)): string._tainted
    //#output(String clipStringifNeeded(JComponent, String, int)): java.lang.StringBuilder:toString(...)._tainted
    //#output(String clipStringifNeeded(JComponent, String, int)): return_value
    //#new obj(String clipStringifNeeded(JComponent, String, int)): java.lang.StringBuilder:toString(...)
    //#pre[2] (String clipStringifNeeded(JComponent, String, int)): (soft) component != null
    //#post(String clipStringifNeeded(JComponent, String, int)): init'ed(java.lang.StringBuilder:toString(...)._tainted)
    //#post(String clipStringifNeeded(JComponent, String, int)): return_value == One-of{&"", &java.lang.StringBuilder:toString(...), string}
    //#post(String clipStringifNeeded(JComponent, String, int)): return_value != null
    //#unanalyzed(String clipStringifNeeded(JComponent, String, int)): Effects-of-calling:java.lang.String:equals
    //#unanalyzed(String clipStringifNeeded(JComponent, String, int)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(String clipStringifNeeded(JComponent, String, int)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(String clipStringifNeeded(JComponent, String, int)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(String clipStringifNeeded(JComponent, String, int)): Effects-of-calling:javax.swing.JComponent:getFont
    //#unanalyzed(String clipStringifNeeded(JComponent, String, int)): Effects-of-calling:javax.swing.JComponent:getFontMetrics
    //#unanalyzed(String clipStringifNeeded(JComponent, String, int)): Effects-of-calling:javax.swing.SwingUtilities:computeStringWidth
    //#unanalyzed(String clipStringifNeeded(JComponent, String, int)): Effects-of-calling:java.lang.String:length
    //#unanalyzed(String clipStringifNeeded(JComponent, String, int)): Effects-of-calling:java.lang.String:charAt
    //#unanalyzed(String clipStringifNeeded(JComponent, String, int)): Effects-of-calling:java.awt.FontMetrics:charWidth
    //#unanalyzed(String clipStringifNeeded(JComponent, String, int)): Effects-of-calling:java.lang.String:substring
    //#test_vector(String clipStringifNeeded(JComponent, String, int)): string: Addr_Set{null}, Inverse{null}
    //#test_vector(String clipStringifNeeded(JComponent, String, int)): java.lang.String:equals(...)@292: {0}, {1}
            return "";
        }
        final FontMetrics fm = component.getFontMetrics(component.getFont());
        final int width = SwingUtilities.computeStringWidth(fm, string);
        if (width > avaiableWidth) {
             return clipString(component, string, avaiableWidth);
         }
        return string;
    //#UIUtilities.java:300: end of method: String com.dmdirc.addons.ui_swing.UIUtilities.clipStringifNeeded(JComponent, String, int)
    }
     /**
     * Clips the passed string .
     * 
     * @param component Component containing string
     * @param string String to check
     * @param avaiableWidth Available Width
     * 
     * @return String (clipped if required)
     */
    public static String clipString(final JComponent component, 
            final String string, final int avaiableWidth) {
        if ((string == null) || (string.equals(""))) {
    //#UIUtilities.java:313: method: String com.dmdirc.addons.ui_swing.UIUtilities.clipString(JComponent, String, int)
    //#input(String clipString(JComponent, String, int)): "..."._tainted
    //#input(String clipString(JComponent, String, int)): avaiableWidth
    //#input(String clipString(JComponent, String, int)): component
    //#input(String clipString(JComponent, String, int)): string
    //#input(String clipString(JComponent, String, int)): string._tainted
    //#output(String clipString(JComponent, String, int)): java.lang.StringBuilder:toString(...)._tainted
    //#output(String clipString(JComponent, String, int)): return_value
    //#new obj(String clipString(JComponent, String, int)): java.lang.StringBuilder:toString(...)
    //#pre[2] (String clipString(JComponent, String, int)): (soft) component != null
    //#presumption(String clipString(JComponent, String, int)): javax.swing.JComponent:getFontMetrics(...)@316 != null
    //#post(String clipString(JComponent, String, int)): init'ed(java.lang.StringBuilder:toString(...)._tainted)
    //#post(String clipString(JComponent, String, int)): return_value in Addr_Set{&"",&java.lang.StringBuilder:toString(...)}
    //#test_vector(String clipString(JComponent, String, int)): string: Addr_Set{null}, Inverse{null}
    //#test_vector(String clipString(JComponent, String, int)): java.lang.String:equals(...)@313: {0}, {1}
            return "";
        }
        final FontMetrics fm = component.getFontMetrics(component.getFont());
        final String clipString = "...";
    //#UIUtilities.java:317: Warning: unused assignment
    //#    Unused assignment into clipString
    //#    severity: LOW
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: String clipString(JComponent, String, int)
        int width = SwingUtilities.computeStringWidth(fm, clipString);
        
         int nChars = 0;
         for(int max = string.length(); nChars < max; nChars++) {
             width += fm.charWidth(string.charAt(nChars));
    //#UIUtilities.java:322: ?overflow
    //#    width + java/awt/FontMetrics:charWidth(...) in {-2_147_483_648..4_294_967_295}
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.addons.ui_swing.UIUtilities
    //#    method: String clipString(JComponent, String, int)
    //#    basic block: bb_6
    //#    assertion: width + java/awt/FontMetrics:charWidth(...) in {-2_147_483_648..4_294_967_295}
    //#    VN: java.awt.FontMetrics:charWidth(...)@322 + width
    //#    Expected: {-2_147_483_648..4_294_967_295, Invalid}
    //#    Bad: {-4_294_967_296..-2_147_483_649, 4_294_967_296..8_589_934_590}
    //#    Attribs:  Int  Bad < Exp  Bad > Exp
             if (width > avaiableWidth) {
                 break;
             }
         }
         return string.substring(0, nChars) + clipString;
    //#UIUtilities.java:327: end of method: String com.dmdirc.addons.ui_swing.UIUtilities.clipString(JComponent, String, int)
    }

}
    //#UIUtilities.java:: end of class: com.dmdirc.addons.ui_swing.UIUtilities
