0N/A/*
3801N/A * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
0N/A *
0N/A * Redistribution and use in source and binary forms, with or without
0N/A * modification, are permitted provided that the following conditions
0N/A * are met:
0N/A *
0N/A * - Redistributions of source code must retain the above copyright
0N/A * notice, this list of conditions and the following disclaimer.
0N/A *
0N/A * - Redistributions in binary form must reproduce the above copyright
0N/A * notice, this list of conditions and the following disclaimer in the
0N/A * documentation and/or other materials provided with the distribution.
0N/A *
2362N/A * - Neither the name of Oracle nor the names of its
0N/A * contributors may be used to endorse or promote products derived
0N/A * from this software without specific prior written permission.
0N/A *
0N/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
0N/A * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
0N/A * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0N/A * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0N/A * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0N/A * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0N/A * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0N/A * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0N/A * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0N/A * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0N/A * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0N/A */
0N/A
0N/A/*
4378N/A * This source code is provided to illustrate the usage of a given feature
4378N/A * or technique and has been deliberately simplified. Additional steps
4378N/A * required for a production-quality application, such as security checks,
4378N/A * input validation and proper error handling, might not be present in
4378N/A * this sample code.
4378N/A */
4378N/A
4378N/A
4378N/A/*
0N/A */
0N/A
0N/Aimport java.awt.BorderLayout;
0N/Aimport java.awt.Font;
0N/Aimport java.awt.event.ActionEvent;
0N/Aimport java.awt.event.ActionListener;
0N/Aimport java.awt.event.ItemEvent;
0N/Aimport java.awt.event.ItemListener;
0N/A
0N/Aimport javax.swing.*;
0N/A
3801N/Aimport java.util.*;
3801N/Aimport java.util.regex.*;
3801N/A
0N/A/**
0N/A * RangeMenu.java
0N/A *
0N/A * @author Shinsuke Fukuda
0N/A * @author Ankit Patel [Conversion to Swing - 01/07/30]
0N/A */
0N/A
0N/A/// Custom made choice menu that holds data for unicode range
0N/A
0N/Apublic final class RangeMenu extends JComboBox implements ActionListener {
0N/A
3801N/A private static final int[][] UNICODE_RANGES = getUnicodeRanges();
3801N/A private static final String[] UNICODE_RANGE_NAMES = getUnicodeRangeNames();
0N/A
0N/A private boolean useCustomRange = false;
0N/A private int[] customRange = { 0x0000, 0x007f };
0N/A
0N/A /// Custom range dialog variables
0N/A private final JDialog customRangeDialog;
0N/A private final JTextField customRangeStart = new JTextField( "0000", 4 );
0N/A private final JTextField customRangeEnd = new JTextField( "007F", 4 );
0N/A private final int CUSTOM_RANGE_INDEX = UNICODE_RANGE_NAMES.length - 1;
0N/A
0N/A /// Parent Font2DTest Object holder
0N/A private final Font2DTest parent;
0N/A
0N/A public static final int SURROGATES_AREA_INDEX = 91;
0N/A
0N/A public RangeMenu( Font2DTest demo, JFrame f ) {
0N/A super();
0N/A parent = demo;
0N/A
0N/A for ( int i = 0; i < UNICODE_RANGE_NAMES.length; i++ )
0N/A addItem( UNICODE_RANGE_NAMES[i] );
0N/A
0N/A setSelectedIndex( 0 );
0N/A addActionListener( this );
0N/A
0N/A /// Set up custom range dialog...
0N/A customRangeDialog = new JDialog( f, "Custom Unicode Range", true );
0N/A customRangeDialog.setResizable( false );
0N/A
0N/A JPanel dialogTop = new JPanel();
0N/A JPanel dialogBottom = new JPanel();
0N/A JButton okButton = new JButton("OK");
0N/A JLabel from = new JLabel( "From:" );
0N/A JLabel to = new JLabel("To:");
0N/A Font labelFont = new Font( "dialog", Font.BOLD, 12 );
0N/A from.setFont( labelFont );
0N/A to.setFont( labelFont );
0N/A okButton.setFont( labelFont );
0N/A
0N/A dialogTop.add( from );
0N/A dialogTop.add( customRangeStart );
0N/A dialogTop.add( to );
0N/A dialogTop.add( customRangeEnd );
0N/A dialogBottom.add( okButton );
0N/A okButton.addActionListener( this );
0N/A
0N/A customRangeDialog.getContentPane().setLayout( new BorderLayout() );
0N/A customRangeDialog.getContentPane().add( "North", dialogTop );
0N/A customRangeDialog.getContentPane().add( "South", dialogBottom );
0N/A customRangeDialog.pack();
0N/A }
0N/A
0N/A /// Return the range that is currently selected
0N/A
0N/A public int[] getSelectedRange() {
0N/A if ( useCustomRange ) {
0N/A int startIndex, endIndex;
0N/A String startText, endText;
0N/A String empty = "";
0N/A try {
0N/A startText = customRangeStart.getText().trim();
0N/A endText = customRangeEnd.getText().trim();
0N/A if ( startText.equals(empty) && !endText.equals(empty) ) {
0N/A endIndex = Integer.parseInt( endText, 16 );
0N/A startIndex = endIndex - 7*25;
0N/A }
0N/A else if ( !startText.equals(empty) && endText.equals(empty) ) {
0N/A startIndex = Integer.parseInt( startText, 16 );
0N/A endIndex = startIndex + 7*25;
0N/A }
0N/A else {
0N/A startIndex = Integer.parseInt( customRangeStart.getText(), 16 );
0N/A endIndex = Integer.parseInt( customRangeEnd.getText(), 16 );
0N/A }
0N/A }
0N/A catch ( Exception e ) {
0N/A /// Error in parsing the hex number ---
0N/A /// Reset the range to what it was before and return that
0N/A customRangeStart.setText( Integer.toString( customRange[0], 16 ));
0N/A customRangeEnd.setText( Integer.toString( customRange[1], 16 ));
0N/A return customRange;
0N/A }
0N/A
0N/A if ( startIndex < 0 )
0N/A startIndex = 0;
0N/A if ( endIndex > 0xffff )
0N/A endIndex = 0xffff;
0N/A if ( startIndex > endIndex )
0N/A startIndex = endIndex;
0N/A
0N/A customRange[0] = startIndex;
0N/A customRange[1] = endIndex;
0N/A return customRange;
0N/A }
0N/A else
0N/A return UNICODE_RANGES[ getSelectedIndex() ];
0N/A }
0N/A
0N/A /// Function used by loadOptions in Font2DTest main panel
0N/A /// to reset setting and range selection
0N/A public void setSelectedRange( String name, int start, int end ) {
0N/A setSelectedItem( name );
0N/A customRange[0] = start;
0N/A customRange[1] = end;
0N/A parent.fireRangeChanged();
0N/A }
0N/A
0N/A /// ActionListener interface function
0N/A /// ABP
0N/A /// moved JComboBox event code into this fcn from
0N/A /// itemStateChanged() method. Part of change to Swing.
0N/A public void actionPerformed( ActionEvent e ) {
0N/A Object source = e.getSource();
0N/A
0N/A if ( source instanceof JComboBox ) {
0N/A String rangeName = (String)((JComboBox)source).getSelectedItem();
0N/A
0N/A if ( rangeName.equals("Custom...") ) {
0N/A useCustomRange = true;
0N/A customRangeDialog.setLocationRelativeTo(parent);
0N/A customRangeDialog.show();
0N/A }
0N/A else {
0N/A useCustomRange = false;
0N/A }
0N/A parent.fireRangeChanged();
0N/A }
0N/A else if ( source instanceof JButton ) {
0N/A /// Since it is only "OK" button that sends any action here...
0N/A customRangeDialog.hide();
0N/A }
0N/A }
3801N/A
3801N/A private static int[][] getUnicodeRanges() {
3801N/A List<Integer> ranges = new ArrayList<>();
3801N/A ranges.add(0);
3801N/A Character.UnicodeBlock currentBlock = Character.UnicodeBlock.of(0);
3801N/A for (int cp = 0x000001; cp < 0x110000; cp++ ) {
3801N/A Character.UnicodeBlock ub = Character.UnicodeBlock.of(cp);
3801N/A if (currentBlock == null) {
3801N/A if (ub != null) {
3801N/A ranges.add(cp);
3801N/A currentBlock = ub;
3801N/A }
3801N/A } else { // being in some unicode range
3801N/A if (ub == null) {
3801N/A ranges.add(cp - 1);
3801N/A currentBlock = null;
3801N/A } else if (cp == 0x10ffff) { // end of last block
3801N/A ranges.add(cp);
3801N/A } else if (! ub.equals(currentBlock)) {
3801N/A ranges.add(cp - 1);
3801N/A ranges.add(cp);
3801N/A currentBlock = ub;
3801N/A }
3801N/A }
3801N/A }
3801N/A ranges.add(0x00); // for user defined range.
3801N/A ranges.add(0x7f); // for user defined range.
3801N/A
3801N/A int[][] returnval = new int[ranges.size() / 2][2];
3801N/A for (int i = 0 ; i < ranges.size() / 2 ; i++ ) {
3801N/A returnval[i][0] = ranges.get(2*i);
3801N/A returnval[i][1] = ranges.get(2*i + 1);
3801N/A }
3801N/A return returnval;
3801N/A }
3801N/A
3801N/A private static String[] getUnicodeRangeNames() {
3801N/A String[] names = new String[UNICODE_RANGES.length];
3801N/A for (int i = 0 ; i < names.length ; i++ ) {
3801N/A names[i] = titleCase(
3801N/A Character.UnicodeBlock.of(UNICODE_RANGES[i][0]).toString());
3801N/A }
3801N/A names[names.length - 1] = "Custom...";
3801N/A return names;
3801N/A }
3801N/A
3801N/A private static String titleCase(String str) {
3801N/A str = str.replaceAll("_", " ");
3801N/A Pattern p = Pattern.compile("(^|\\W)([a-z])");
3801N/A Matcher m = p.matcher(str.toLowerCase(Locale.ROOT));
3801N/A StringBuffer sb = new StringBuffer();
3801N/A while (m.find()) {
3801N/A m.appendReplacement(sb, m.group(1) + m.group(2).toUpperCase(Locale.ROOT));
3801N/A }
3801N/A m.appendTail(sb);
3801N/A return sb.toString().replace("Cjk", "CJK").replace("Nko", "NKo");
3801N/A }
0N/A}