/**
* Copyright (c) 2009, Till Woitendorf (t68)
Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:<BR>
1. Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.<BR>
2. Redistributions in binary form must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other materials provided with
the distribution.<BR>
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Contact me via http://jvkeyboard.sourceforge.net if you discover any bugs or if you have a suggestion
*/
package de.t68.utils.keyboard;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
/**
* @author t68
*
*/
public class KeyboardLayout extends LinkedList<LinkedList<LinkedList<KeyboardKey>>> {
public static final String ATTR_CODE = "code";
public static final String ELEMENT_COUNTRY = "Country";
public static final String ELEMENT_COUNTRIES = "Countries";
public static final String XML_ROOT = "KeyboardConfiguration";
public static final String Element_LanguageInfo = "LanguageInfo";
public static final String Attr_Name = "Name";
public static final String Attr_NativeName = "NativeName";
public static final String Attr_Font = "Font";
public static final String Attr_FixedWidthFont = "FixedWidthFont";
public static final String Attr_LocaleString = "LocaleString";
public static final String Element_Keyboard = "Keyboard";
public static final String Element_Line = "Line";
public static final String Show = "Show";
public static final String in = "Input";
public static final String IME = "ImeMode";
public static final String length = "length";
protected String name;
protected String nativeName;
protected String fontName;
protected String fixedWidthFontName;
protected List<String> localeString = new LinkedList<>();
protected int currentKeyboard = 0;
protected List<String> imeList = null;
protected List<String> keyboardID = null;
/** f�r die Zeicheners�tzung der Spezialtasten */
protected List<String> org = null;
protected List<String> trans = null;
public KeyboardLayout(InputStream is) throws Exception
{
SAXBuilder builder = new SAXBuilder();
Document document = builder.build(is);
loadData(document.getRootElement());
}
protected KeyboardLayout()
{// Konstruktor f�r Ableitungen und clone()
}
/**
* Loads the data from the XML Structure.
*
* @param data
*/
protected void loadData(Element data)
{
if (data == null)
throw new IllegalArgumentException("cannot load data, data ist null");
Element li = data.getChild(Element_LanguageInfo);
name = li.getAttributeValue(Attr_Name);
nativeName = li.getAttributeValue(Attr_Name);
fontName = li.getAttributeValue(Attr_Font);
fixedWidthFontName = li.getAttributeValue(Attr_FixedWidthFont);
localeString.add(li.getAttributeValue(Attr_LocaleString));
Element countriesEl = li.getChild(ELEMENT_COUNTRIES);
if (countriesEl != null)
{
List<Element> countries = countriesEl.getChildren(ELEMENT_COUNTRY);
String[] locSplit = localeString.get(0).split("-");
if (countries != null && !countries.isEmpty() && locSplit != null && locSplit.length >= 1)
for (Element country : countries)
localeString.add(locSplit[0] + "-" + country.getAttributeValue(ATTR_CODE));
}
org = new LinkedList<String>();
trans = new LinkedList<String>();
// check the translated keys
Element transKeys = li.getChild(Show);
if (transKeys != null)
for (Element l : transKeys.getChildren(in))
{
org.add(l.getAttribute("org").getValue());
trans.add(l.getAttribute("translate").getValue());
}
imeList = new LinkedList<String>();
// check the IME Mode
for (Element l : li.getChildren(IME))
if (l != null)
imeList.add(l.getAttributeValue(IME));
int tmp = 0;
keyboardID = new LinkedList<String>();
currentKeyboard = -1;
for (Element board : li.getChildren(Element_Keyboard))
{
String idIME = null;
if (board.getAttribute("ID") != null)
{
idIME = board.getAttribute("ID").getValue();
// save a list of keyboard ID's
keyboardID.add(idIME);
}
currentKeyboard++;
add(new LinkedList<LinkedList<KeyboardKey>>());
for (Element lineEl : board.getChildren(Element_Line))
{
LinkedList<KeyboardKey> line = new LinkedList<KeyboardKey>();
get(currentKeyboard).add(line);
for (Element keyEl : lineEl.getChildren(KeyboardKey.Element_Key))
{
String special = keyEl.getAttributeValue(SpecialKey.Attr_Special);
// basic key
if (special == null || special.length() == 0)
line.add(new KeyboardKey(fontName, keyEl));
else
{
SpecialKey skey = (SpecialKey) SpecialKey.getKeyboardKey(fontName, special);
if (skey != null)
{
// fill the IME button with content
if (skey.textToShow == "IME" && idIME != null)
{
skey.textToShow = imeList.get(tmp);
if (tmp < imeList.size() - 1)
tmp++;
else
tmp = 0;
}
for (int f = 0; f < org.size(); f++)
if (special.equals(org.get(f)))
{
skey.textToShow = trans.get(f);
f = org.size();
}
Attribute a;
if ((a = keyEl.getAttribute(length)) != null)
skey.keyWidth = Integer.parseInt(a.getValue());
line.add(skey);
} else
line.add(SpecialKey.getKeyboardKey(fontName, special));
}
}
}
}
currentKeyboard = 0;
}
@Override
public String toString()
{
return nativeName + " - " + name;
}
public List<String> getLocaleString()
{
return localeString;
}
public Element getAsElement()
{
Element root = new Element("KeyboardConfiguration");
Element li = new Element(Element_LanguageInfo);
root.addContent(li);
li.setAttribute(Attr_Name, name);
li.setAttribute(Attr_NativeName, nativeName);
li.setAttribute(Attr_Font, fontName);
li.setAttribute(Attr_FixedWidthFont, fixedWidthFontName);
li.setAttribute(Attr_LocaleString, localeString.isEmpty() ? "international" : localeString.get(0));
if (localeString.size() > 1)
{
Element countries = new Element(ELEMENT_COUNTRIES);
for (int i = 1; i < localeString.size(); i++)
{
String[] split = localeString.get(i).split("-");
if (split != null && split.length == 2)
{
Element country = new Element(ELEMENT_COUNTRY);
country.setAttribute(ATTR_CODE, split[1]);
countries.addContent(country);
}
}
if (countries.getChildren().isEmpty())
li.addContent(countries);
}
Element keyboard;
// backwards Translation key
if (org.size() > 0)
{
Element et = new Element(Show);
li.setContent(et);
for (int f = 0; f < org.size(); f++)
{
Element ett = new Element(in);
et.addContent(ett);
ett.setAttribute(new org.jdom2.Attribute("org", org.get(f)));
ett.setAttribute(new org.jdom2.Attribute("translate", trans.get(f)));
}
}
if (imeList.size() > 0)
for (int f = 0; f < imeList.size(); f++)
{
Element et = new Element(IME);
et.setAttribute(new org.jdom2.Attribute(IME, imeList.get(f)));
li.addContent(et);
}
for (int i = 0; i < size(); i++)
{
keyboard = new Element(Element_Keyboard);
li.addContent(keyboard);
for (LinkedList<KeyboardKey> list : this.get(i))
{
Element line = new Element(Element_Line);
keyboard.addContent(line);
for (KeyboardKey kk : list)
line.addContent(kk.getAsElement());
}
}
return root;
}
/**
* search the keyboard number by the keyboard id
* */
public int getNumberByKeyboardID(String id)
{
for (int i = 0; i < keyboardID.size(); i++)
if (keyboardID.get(i).endsWith(id))
return i;
return -1;
}
@Override
public Object clone()
{
KeyboardLayout clone = null;
clone = (KeyboardLayout) super.clone();
clone.imeList = new LinkedList<String>();
clone.keyboardID = new LinkedList<String>();
clone.org = new LinkedList<String>();
clone.trans = new LinkedList<String>();
for (String s : imeList)
clone.imeList.add(new String(s));
for (String s : keyboardID)
clone.keyboardID.add(new String(s));
for (String s : org)
clone.org.add(new String(s));
for (String s : trans)
clone.trans.add(new String(s));
return clone;
}
}