Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic toggling of character width by Windows 7 input methods in Java

I have a couple of input methods for writing (Traditional Chinese) Taiwanese that come with the Windows 7. Also, all of the input methods have an option to switch the character width (single byte/double byte characters).

  • Chinese (Traditional) - New Quick
  • Chinese (Traditional) - ChangJie
  • Chinese (Traditional) - Quick
  • Chinese (Traditional) - Phonetic
  • Chinese (Traditional) - New Phonetic
  • Chinese (Traditional) - New ChangJie

If I select one of these input methods in Java application and set the character width to half-width(single byte character mode) i can successfully input text in JTextField. But, if the application displays some dialog box (e.g. JOptionPane) or pop up window, the input method character width will automatically change to full-width(double byte character mode). After that, the user must manually toggle to half-width characters.

I can programmatically switch on or off the input method using the Java class "InputContext", but i can't control if the input method is set to full-width/half-width (single/double byte) character mode.

I thought maybe it could be disabled from the Windows input method settings, but there was no option related to automatic switching of the character width.

The question is: Is there a way to handle (disable) this automatic toggling ?

Here is an example code to test this with the above input methods:

public class Example implements ActionListener {

    JFrame f = new JFrame("pasod");
    JTextField txt = new JTextField();
    Button btn = new Button("Locale");

    public Example() {

        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout());
        btn.addActionListener(this);
        panel.add(btn);
        panel.add(txt);
        f.add(panel);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.pack();
        f.setSize(800, 100);
        f.setVisible(true);
    }   

    public static void main(String[] args) {
        new Example();              
    }

    public void actionPerformed(ActionEvent arg0) {
        JOptionPane.showMessageDialog(btn, "Neso", "Neso",
                 JOptionPane.INFORMATION_MESSAGE);
    }
}

Thanks.

like image 518
Daltonito Avatar asked May 27 '13 13:05

Daltonito


Video Answer


1 Answers

Ok I've had a trace through the Java source code looking for anything that stands out;

You call JOptionPane.showMessageDialog() this overloads to JOptionPane.showOptionDialog();

public static int showOptionDialog(Component parentComponent,
        Object message, String title, int optionType, int messageType,
        Icon icon, Object[] options, Object initialValue) 
        throws HeadlessException {
        JOptionPane             pane = new JOptionPane(message, messageType,
                                                       optionType, icon,
                                                       options, initialValue);

        pane.setInitialValue(initialValue);
        pane.setComponentOrientation(((parentComponent == null) ?
        getRootFrame() : parentComponent).getComponentOrientation());

        int style = styleFromMessageType(messageType);
        JDialog dialog = pane.createDialog(parentComponent, title, style);

        pane.selectInitialValue();
        dialog.show();    
        //..Result handling code
    }

So we look into createDialog();

public JDialog createDialog(String title) throws HeadlessException {
    int style = styleFromMessageType(getMessageType());
    JDialog dialog = new JDialog((Dialog) null, title, true);
    initDialog(dialog, style, null);
    return dialog;
}

So we check the constructor/s of JDialog these all call dialogInit();

protected void dialogInit() {
    enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK);
    setLocale( JComponent.getDefaultLocale() );
    setRootPane(createRootPane());
    setRootPaneCheckingEnabled(true);
    if (JDialog.isDefaultLookAndFeelDecorated()) {
        boolean supportsWindowDecorations = 
        UIManager.getLookAndFeel().getSupportsWindowDecorations();
        if (supportsWindowDecorations) {
            setUndecorated(true);
            getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);
        }
    }
    sun.awt.SunToolkit.checkAndSetPolicy(this, true);
}

Here we've found setLocale( JComponent.getDefaultLocale() );;

So it appears whenever you create a JDialog, whether it be indirect or not the locale of your program is reset to default, I'm guessing this includes resetting your input settings.

There are a few ways you can set the default Locale (programatically, system properties or runtime args); Details found here

Hope that helps you

like image 172
Robadob Avatar answered Oct 12 '22 23:10

Robadob