/*
GNU General Public License
CacheWolf is a software for PocketPC, Win and Linux that
enables paperless caching.
It supports the sites geocaching.com and opencaching.de
Copyright (C) 2006 CacheWolf development team
See http://www.cachewolf.de/ for more information.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package CacheWolf.navi.touchControls;
import CacheWolf.Preferences;
import CacheWolf.utils.MyLocale;
import CacheWolf.navi.touchControls.MovingMapControlItemText.TextOptions;
import CacheWolf.navi.touchControls.MovingMapControls.Role;
import ewe.io.File;
import ewe.io.FileBase;
import ewe.sys.Vm;
import ewe.util.Hashtable;
import ewe.util.Vector;
import ewe.util.mString;
import ewesoft.xml.MinML;
import ewesoft.xml.sax.AttributeList;
import ewesoft.xml.sax.SAXException;
public class MovingMapControlSettings extends MinML implements ICommandListener {
public static final String CONFIG_FILE_NAME = "movingMapControls.xml";
public static final String CONFIG_FILE_NAME_OVERWRITE = "my_movingMapControls.xml";
public static String CONFIG_RELATIVE_PATH = "mmc/";
public static final String SETTINGS = "settings";
/**
* the size of the font on the icons
*/
public static final String SETTINGS_ATTR_FONTSIZE = "fontsize";
public static final String ROLE = "role";
/**
* name of the role [String]
*/
public static final String ROLE_ATTR_NAME = "name";
/**
* the inital state of the role [true|false]
*/
public static final String ROLE_ATTR_ACTIVE = "active";
/**
* A list of roles to disable, if this role changes the state from active to inactive. Delimiter is '|'.
* [String|String|...]
*/
public static final String ROLE_ATTR_DISABLE = "disable";
public static final String BUTTON = "button";
/**
* position of the left upper corner of the button from the left screen border [int (pixel)]
*/
public static final String BUTTON_ATTR_FROM_LEFT = "fromLeft";
/**
* position of the left upper corner of the button from the upper screen border [int (pixel)]
*/
public static final String BUTTON_ATTR_FROM_TOP = "fromTop";
/**
* position of the left upper corner of the button from the right screen border. If fromLeft is set, this option
* will not be read! [int (pixel)]
*/
public static final String BUTTON_ATTR_FROM_RIGHT = "fromRight";
/**
* position of the left upper corner of the button from the bottom screen border. If fromTop is set, this option
* will not be read! [int (pixel)]
*/
public static final String BUTTON_ATTR_FROM_BOTTOM = "fromBottom";
/**
* define when this button is visible. Contains a list of rolenames. Delimiter is '+'. If the role name starts with
* '!' the button is shown if this role is inactive [(!)String+(!)String...] Example visibleIf="menu+!zoom" button
* is visible if role "menu" is active and role "zoom" is inactive.
*/
public static final String BUTTON_ATTR_VISIBILITY = "visibleIf";
/**
* the id of the text in the language file
*/
public static final String BUTTON_ATTR_LOCALE_ID = "localeID";
/**
* the default text on the button if no localID is set or found.
*/
public static final String BUTTON_ATTR_LOCALE_DEFAULT = "localeDefault";
/**
* the alpha value set the level of transparency of the button. [0-255]
*/
public static final String BUTTON_ATTR_ALPHA = "alpha";
/**
* the file path and name of the button
*/
public static final String BUTTON_ATTR_LOCATION = "location";
/**
* the file path and name of the icon which can be displayed on the button
*/
public static final String BUTTON_ATTR_ICON = "icon";
public static final String BUTTON_ATTR_ICON_OFFSET_X = "iconX";
public static final String BUTTON_ATTR_ICON_OFFSET_Y = "iconY";
public static final String BUTTON_ATTR_TEXT_OFFSET_L = "textOffsetLeft";
public static final String BUTTON_ATTR_TEXT_OFFSET_R = "textOffsetRight";
public static final String BUTTON_ATTR_TEXT_OFFSET_T = "textOffsetTop";
public static final String BUTTON_ATTR_TEXT_OFFSET_B = "textOffsetBottom";
/**
* the action command. Defines what is to do if the button is clicked
*/
public static final String BUTTON_ATTR_ACTION = "action";
/**
* if the defined action is "changeStateOfRole", this attribute defines which role state should be changed [String]
*/
public static final String BUTTON_ATTR_CHANGE_STAE_OF = "changeStateof";
/**
* the name of content which is displayed on the button.
* Currently the content distance, scale, hdop, sats are known.
*/
public static final String BUTTON_ATTR_CONTENT = "content";
/**
* the alignment of the text on the buttons. if the String starts with 'T' the text will be displayed on the top
* line of the button if the String starts with 'B' the text will be displayed on the bottom line of the button if
* the String starts ends 'L' the text will be displayed on the left side of the button if the String starts ends
* 'R' the text will be displayed on the right side of the button otherwise horizontal and vertical center will be
* used as default
*/
public static final String BUTTON_ATTR_ALIGNTEXT = "alignText";
Vector menuItems = new Vector(10);
private Hashtable roles;
private int fontsize;
public MovingMapControlSettings(boolean vga, Hashtable roles) {
double fontscale = vga ? 1.5 : 1;
this.fontsize = (int) (Preferences.itself().fontSize * fontscale);
this.roles = roles;
}
public void startElement(String name, AttributeList attributes) throws SAXException {
if (name.equals(SETTINGS)) {
String fontsizeString = attributes.getValue(SETTINGS_ATTR_FONTSIZE);
if (fontsizeString != null) {
try {
fontsize = Integer.parseInt(fontsizeString);
}
catch (Exception e) {
Preferences.itself().log("fontsize not an int " + fontsizeString, e);
}
}
}
if (name.equals(ROLE)) {
String role_name = attributes.getValue(ROLE_ATTR_NAME);
String role_active = attributes.getValue(ROLE_ATTR_ACTIVE);
String disable = attributes.getValue(ROLE_ATTR_DISABLE);
if (role_name != null) {
Role r = new Role();
roles.put(role_name, r);
if (role_active != null) {
r.setState(true);
}
if (disable != null) {
r.setRolesToDisable(mString.split(disable));
}
}
}
if (name.equals(BUTTON)) {
int xProperties = 0;
String fromLeft = attributes.getValue(BUTTON_ATTR_FROM_LEFT);
String fromRight = attributes.getValue(BUTTON_ATTR_FROM_RIGHT);
String fromTop = attributes.getValue(BUTTON_ATTR_FROM_TOP);
String fromBottom = attributes.getValue(BUTTON_ATTR_FROM_BOTTOM);
int xpos = toIntValue(fromLeft);
if (xpos < 0) {
xpos = toIntValue(fromRight);
xProperties |= MovingMapControlItem.DISPLAY_FROM_RIGHT;
}
else {
xProperties |= MovingMapControlItem.DISPLAY_FROM_LEFT;
}
int ypos = toIntValue(fromTop);
if (ypos < 0) {
ypos = toIntValue(fromBottom);
xProperties |= MovingMapControlItem.DISPLAY_FROM_BOTTOM;
}
else {
xProperties |= MovingMapControlItem.DISPLAY_FROM_TOP;
}
if (xpos < 0) {
Preferences.itself().log("the x position of the button has to be set! " + "use attribute '" + BUTTON_ATTR_FROM_LEFT + "' or '" + BUTTON_ATTR_FROM_RIGHT + "'", null);
xpos = 0;
}
if (ypos < 0) {
Preferences.itself().log("the y position of the button has to be set! " + "use attribute '" + BUTTON_ATTR_FROM_TOP + "' or '" + BUTTON_ATTR_FROM_BOTTOM + "'", null);
ypos = 0;
}
String changeState = attributes.getValue(BUTTON_ATTR_CHANGE_STAE_OF);
String visibility = attributes.getValue(BUTTON_ATTR_VISIBILITY);
int action = getCommand(attributes.getValue(BUTTON_ATTR_ACTION));
String localeDefault = attributes.getValue(BUTTON_ATTR_LOCALE_DEFAULT);
String imageLocation = attributes.getValue(BUTTON_ATTR_LOCATION);
String iconLocation = attributes.getValue(BUTTON_ATTR_ICON);
if (iconLocation != null) {
iconLocation = CONFIG_RELATIVE_PATH + iconLocation;
}
String alignText = attributes.getValue(BUTTON_ATTR_ALIGNTEXT);
String content = attributes.getValue(BUTTON_ATTR_CONTENT);
if (visibility == null) {
Preferences.itself().log("read MovingMap settings: " + BUTTON_ATTR_VISIBILITY + " not set!", null);
return;
}
if (action == -2) {
Preferences.itself().log("read MovingMap settings: " + BUTTON_ATTR_ACTION + " not set!", null);
return;
}
int alphavalue = getIntFromFile(attributes, BUTTON_ATTR_ALPHA, -1);
int localIDValue = getIntFromFile(attributes, BUTTON_ATTR_LOCALE_ID, 0);
if (imageLocation == null) {
// something not set
Preferences.itself().log("Image for '" + localeDefault + "' not found", null);
return;
}
else {
imageLocation = CONFIG_RELATIVE_PATH + imageLocation;
}
int localfontsize = getIntFromFile(attributes, SETTINGS_ATTR_FONTSIZE, fontsize);
// textoptions
TextOptions tOptions = new TextOptions(localfontsize, getIntFromFile(attributes, BUTTON_ATTR_TEXT_OFFSET_L, 0), getIntFromFile(attributes, BUTTON_ATTR_TEXT_OFFSET_R, 0), getIntFromFile(attributes, BUTTON_ATTR_TEXT_OFFSET_T, 0),
getIntFromFile(attributes, BUTTON_ATTR_TEXT_OFFSET_B, 0));
MovingMapControlItem button;
String itemText;
if (localeDefault == null)
itemText = MyLocale.getMsg(localIDValue, "");
else
itemText = MyLocale.getMsg(localIDValue, localeDefault);
if (itemText.equals("") && content == null) {
button = new MovingMapControlItemButton(imageLocation, iconLocation, action, alphavalue);
}
else {
button = new MovingMapControlItemText(itemText, imageLocation, iconLocation, alphavalue, action, content, alignText, tOptions);
}
// add extra role to all icons
visibility += "+!" + MovingMapControls.ROLE_WORKING;
button.setVisibilityRole(visibility);
if (changeState != null) {
button.setRole(changeState);
}
button.setPosition(xpos, ypos);
button.addXtraProperties(xProperties);
menuItems.add(button);
}
}
private int getCommand(String value) {
if (value == null)
return -2;
else if (value.equals("selectMap"))
return SELECT_MAP;
else if (value.equals("changeMapDir"))
return CHANGE_MAP_DIR;
else if (value.equals("moveToGps"))
return MOVE_TO_GPS;
else if (value.equals("moveToDest"))
return MOVE_TO_DEST;
else if (value.equals("moveToCenter"))
return MOVE_TO_CENTER;
else if (value.equals("allCachesRes"))
return ALL_CACHES_RES;
else if (value.equals("moreOverview"))
return MORE_OVERVIEW;
else if (value.equals("moreDetails"))
return MORE_DETAILS;
else if (value.equals("keepManResolution"))
return KEEP_MAN_RESOLUTION;
else if (value.equals("changeStateOfRole"))
return changeStateOfRole;
else if (value.equals("highestResolution"))
return HIGHEST_RES;
else if (value.equals("highestResGpsDest"))
return HIGHEST_RES_GPS_DEST;
else if (value.equals("showMap"))
return SHOW_MAP;
else if (value.equals("hideMap"))
return HIDE_MAP;
else if (value.equals("menu"))
return SHOW_MENU;
else if (value.equals("hide_menu"))
return HIDE_MENU;
else if (value.equals("show_caches"))
return SHOW_CACHES;
else if (value.equals("hide_caches"))
return HIDE_CACHES;
else if (value.equals("zoomin"))
return ZOOMIN;
else if (value.equals("zoomout"))
return ZOOMOUT;
else if (value.equals("1to1"))
return ZOOM_1_TO_1;
else if (value.equals("map_moved"))
return MAP_MOVED;
else if (value.equals("pos_updated"))
return POS_UPDATED;
else if (value.equals("goto_updated"))
return GOTO_UPDATED;
else if (value.equals("close"))
return CLOSE;
else if (value.equals("fillMap"))
return FILL_MAP;
else if (value.equals("nofillMap"))
return NO_FILL_MAP;
else if (value.equals("context_goto"))
return CONTEXT_GOTO;
else if (value.equals("context_nwp"))
return CONTEXT_NEW_WAY_POINT;
else if (value.equals("context_ocDesc"))
return CONTEXT_OPEN_CACHE_DESC;
else if (value.equals("context_ocDetail"))
return CONTEXT_OPEN_CACHE_DETAIL;
else if (value.equals("context_goto_cache"))
return CONTEXT_GOTO_CACHE;
else if (value.equals("context_tour"))
return CONTEXT_TOUR;
else
return -1;
}
private int getIntFromFile(AttributeList attributes, String field, int defaultValue) {
String entry = attributes.getValue(field);
if (entry != null) {
try {
defaultValue = Integer.parseInt(entry);
}
catch (Exception e) {
Preferences.itself().log("Can not read int for filed " + field + ": " + entry, e);
}
}
return defaultValue;
}
private int toIntValue(String pos) {
try {
return Integer.parseInt(pos);
}
catch (Exception e) {
return -1;
}
}
public boolean readFile() {
setDocumentHandler(this);
String tmp = CONFIG_RELATIVE_PATH + "Desktop/";
if (Vm.isMobile()) {
tmp = CONFIG_RELATIVE_PATH + "pda/";
if (Preferences.itself().getScreenHeight() >= 480 && Preferences.itself().getScreenWidth() >= 480) {
tmp = CONFIG_RELATIVE_PATH + "pda_vga/";
}
}
CONFIG_RELATIVE_PATH = tmp;
String path = FileBase.makePath(FileBase.getProgramDirectory(), CONFIG_RELATIVE_PATH);
path = path.replace('\\', '/');
File file = new File(path, CONFIG_FILE_NAME_OVERWRITE);
if (!file.exists()) {
file = new File(path, "" + Preferences.itself().getScreenWidth() + "x" + Preferences.itself().getScreenHeight() + ".xml");
}
if (!file.exists()) {
file = new File(path, CONFIG_FILE_NAME);
}
try {
ewe.io.Reader r = new ewe.io.InputStreamReader(new ewe.io.FileInputStream(file));
parse(r);
r.close();
}
catch (Exception e) {
if (e instanceof NullPointerException)
Preferences.itself().log("Error reading " + path + ": NullPointerException in Element " + "" + ". Wrong attribute, File not existing?", e, true);
else
Preferences.itself().log("Error reading " + path + ": ", e);
return false;
}
return true;
}
public Vector getMenuItems() {
return menuItems;
}
public boolean handleCommand(int command) {
// dummy
return false;
}
}