/* * Copyright � 2008, 2010, Oracle and/or its affiliates. All rights reserved */ package userclasses; import generated.StateMachineBase; import com.sun.lwuit.*; import com.sun.lwuit.animations.Animation; import com.sun.lwuit.animations.CommonTransitions; import com.sun.lwuit.util.*; import com.sun.lwuit.events.*; import com.sun.lwuit.geom.Dimension; import com.sun.lwuit.list.DefaultListModel; import com.sun.lwuit.list.ListModel; import java.util.Date; import java.util.Hashtable; import java.util.TimeZone; /** * Demo code for the t-zone application, most of the code in this class is related to timezone handling. This * class contains the entire code of the application * * @author Shai Almog */ public class StateMachine extends StateMachineBase { private boolean civilianTime; private boolean removeMode; private Image sunImage; private Image moonImage; private boolean friendsMode = true; private static final String[] DAYS = new String[] {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; private static final String[] MONTHS = new String[] {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; private static final int[] TIMEZONE_OFFSETS = new int[] { -12 * 60, -11 * 60, -10 * 60, -95 * 6, -9 * 60, -8 * 60, -7 * 60, -6 * 60, -5 * 60, -45 * 6, -4 * 60, -35 * 6, -3 * 60, -2 * 60, - 60, 0, 60, 2 * 60, 3 * 60, 35 * 6, 4 * 60, 45 * 6, 5 * 60, 55 * 6, 4 * 60, 345, 6 * 60, 65 * 6, 7 * 60, 8 * 60, 525, 9 * 60, 95 * 6, 10 * 60, 630, 660, 690, 720, 765, 780, 840 }; private static final String[] TIMEZONES = new String[] { "UTC-12:00", "UTC-11:00", "UTC-10:00", "UTC-09:30", "UTC-09:00", "UTC-08:00", "UTC-07:00", "UTC-06:00", "UTC-05:00", "UTC-04:30", "UTC-04:00", "UTC-03:30", "UTC-03:00", "UTC-02:00", "UTC-01:00", "UTC", "UTC+01:00", "UTC+02:00", "UTC+03:00", "UTC+03:30", "UTC+04:00", "UTC+04:30", "UTC+05:00", "UTC+05:30", "UTC+05:45", "UTC+06:00", "UTC+06:30", "UTC+07:00", "UTC+08:00", "UTC+08:45", "UTC+09:00", "UTC+09:30", "UTC+10:00", "UTC+10:30", "UTC+11:00", "UTC+11:30", "UTC+12:00", "UTC+12:45", "UTC+13:00", "UTC+14:00" }; private static final Hashtable[] TIMEZONE_ENTRIES = new Hashtable[TIMEZONES.length]; private static final Hashtable[] FRIENDS = new Hashtable[6]; static { for(int iter = 0 ; iter < TIMEZONES.length ; iter++) { TIMEZONE_ENTRIES[iter] = new Hashtable(); TIMEZONE_ENTRIES[iter].put("title", TIMEZONES[iter]); TIMEZONE_ENTRIES[iter].put("zone", new Integer(iter)); if(TIMEZONE_OFFSETS[iter] == 0) { TIMEZONE_ENTRIES[iter].put("selected", "true"); } } FRIENDS[0] = new Hashtable(); FRIENDS[0].put("title", "Chen"); FRIENDS[0].put("description", "LWUIT Daddy"); FRIENDS[0].put("selected", "true"); FRIENDS[0].put("zone", new Integer(4)); FRIENDS[1] = new Hashtable(); FRIENDS[1].put("title", "Shai"); FRIENDS[1].put("description", "Isn't that obvious?"); FRIENDS[1].put("selected", "true"); FRIENDS[1].put("zone", new Integer(10)); FRIENDS[2] = new Hashtable(); FRIENDS[2].put("title", "Ofir"); FRIENDS[2].put("description", "Would you like some HTML with that?"); FRIENDS[2].put("zone", new Integer(12)); FRIENDS[3] = new Hashtable(); FRIENDS[3].put("title", "Yaniv"); FRIENDS[3].put("description", "Can you explain that again?"); FRIENDS[3].put("zone", new Integer(16)); FRIENDS[4] = new Hashtable(); FRIENDS[4].put("title", "Meirav"); FRIENDS[4].put("description", "All that and on high heels"); FRIENDS[4].put("zone", new Integer(20)); FRIENDS[5] = new Hashtable(); FRIENDS[5].put("title", "Martin"); FRIENDS[5].put("description", "Everything that looks decent here is mine"); FRIENDS[5].put("zone", new Integer(23)); } private Animation timeUpdateAnimation = new Animation() { private long lastRun; public boolean animate() { long t = System.currentTimeMillis(); if(t - lastRun > 2500) { Form f = Display.getInstance().getCurrent(); Label subtitle = findSubtitle(f); if(subtitle != null) { lastRun = t; updateTimes(f); } } return false; } public void paint(Graphics grphcs) { } }; private void updateTimes(Form f) { Label subtitle = findSubtitle(f); java.util.Calendar c = java.util.Calendar.getInstance(); c.setTime(new Date()); String s = "My Time: " + timeAndDate(c); subtitle.setText(s); Container friends = findFriendsRoot(f); for(int iter = 0 ; iter < friends.getComponentCount() ; iter++) { Component fr = friends.getComponentAt(iter); if(fr instanceof Container) { updateFriendTime((Container)fr); } } } private String timeAndDate(java.util.Calendar c) { return formatTime(c.get(java.util.Calendar.HOUR_OF_DAY), c.get(java.util.Calendar.MINUTE)) + " " + DAYS[c.get(java.util.Calendar.DAY_OF_WEEK) - 1] + ", " + c.get(java.util.Calendar.DAY_OF_MONTH) + " " + MONTHS[c.get(java.util.Calendar.MONTH)]; } public StateMachine(String resFile) { super(resFile); // do not modify, write code in initVars and initialize class members there, // the constructor might be invoked too late due to race conditions that might occur Resources res = fetchResourceFile(); FRIENDS[0].put("icon", res.getImage("chen.jpg")); FRIENDS[1].put("icon", res.getImage("shai.jpg")); FRIENDS[2].put("icon", res.getImage("ofir.jpg")); FRIENDS[3].put("icon", res.getImage("yaniv.jpg")); FRIENDS[4].put("icon", res.getImage("merav.jpg")); FRIENDS[5].put("icon", res.getImage("martin.jpg")); sunImage = res.getImage("sun.png"); moonImage = res.getImage("moon.png"); } /** * this method should be used to initialize variables instead of * the constructor/class scope to avoid race conditions */ protected void initVars() { } protected boolean initListModelTimeSlider(final List cmp) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.initListModelTimeSlider(cmp); Hashtable[] data = new Hashtable[672]; java.util.Calendar cal = java.util.Calendar.getInstance(); cal.setTime(new Date()); String[] sevenDays = new String[7]; int dow = cal.get(java.util.Calendar.DAY_OF_WEEK) - java.util.Calendar.SUNDAY; for(int iter = 0 ; iter < 7 ; iter++) { cal.setTime(new Date(System.currentTimeMillis() + (24 * 60 * 60 * 1000))); sevenDays[iter] = DAYS[dow] + ", " + cal.get(java.util.Calendar.DAY_OF_MONTH) + " " + MONTHS[cal.get(java.util.Calendar.MONTH)]; dow++; if(dow == DAYS.length) { dow = 0; } } Resources res = fetchResourceFile(); Image longTick; Image shortTick = res.getImage("short_tick.png"); // every little bit counts in a small screen if(Display.getInstance().getDeviceDensity() <= Display.DENSITY_LOW) { longTick = shortTick; } else { longTick = res.getImage("long_tick.png"); } for(int iter = 0 ; iter < data.length ; iter++) { data[iter] = new Hashtable(); data[iter].put("day", sevenDays[iter / 96]); int time = iter % 96 * 15; int minutes = time % 60; data[iter].put("time", twoDigits(time / 60) + ":" + twoDigits(minutes)); if(minutes == 0) { data[iter].put("tick", longTick); data[iter].put("tickLabel", "" + (time / 60)); } else { data[iter].put("tick", shortTick); if(time % 30 == 0) { data[iter].put("tickLabel", "1/2"); } } } final ListModel m = new DefaultListModel(data); m.setSelectedIndex(50); cmp.setModel(m); m.addSelectionListener(new SelectionListener() { public void selectionChanged(int i, int i1) { Hashtable h = (Hashtable)m.getItemAt(i1); if(i1 > -1) { findTimeSliderPosition(cmp.getParent()).setText((String)h.get("day")); findSliderTimeTab(cmp.getParent()).setText((String)h.get("time")); } } }); return true; } private String twoDigits(int i) { if(i < 10) { return "0" + i; } return "" + i; } protected void beforeMainUI(Form f) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.beforeMainUI(f); f.registerAnimated(timeUpdateAnimation); addAllSelectedFriends(f); if(Display.getInstance().getDeviceDensity() <= Display.DENSITY_LOW) { findRemoveModeButton(f).setText(""); findAddEntriesButton(f).setText(""); findExitButton(f).setText(""); findSettingsButton(f).setText(""); } else { if(removeMode) { findRemoveModeButton(f).setText("Finish"); } } } private void addAllSelectedFriends(Form f) { for(int iter = 0 ; iter < FRIENDS.length ; iter++) { String s = (String)FRIENDS[iter].get("selected"); if("true".equals(s)) { addHashtable(f, FRIENDS[iter]); } } for(int iter = 0 ; iter < TIMEZONE_ENTRIES.length ; iter++) { String s = (String)TIMEZONE_ENTRIES[iter].get("selected"); if("true".equals(s)) { addHashtable(f, TIMEZONE_ENTRIES[iter]); } } updateTimes(f); } private void updateFriendTime(Container friend) { Hashtable h = (Hashtable)friend.getClientProperty("data"); int zone = ((Integer)h.get("zone")).intValue(); java.util.Calendar cal = java.util.Calendar.getInstance(TimeZone.getTimeZone("GMT")); cal.setTime(new Date(System.currentTimeMillis() + (TIMEZONE_OFFSETS[zone] * 60000))); String currently = " currently: "; if(Display.getInstance().getDeviceDensity() <= Display.DENSITY_LOW) { currently = ""; } findCurrentTimeAndDate(friend).setText(TIMEZONES[zone] + currently + timeAndDate(cal)); int selection = findTimeSlider(friend.getParent()).getSelectedIndex(); // convert selection to minutes and add the offset selection = selection * 15 + TIMEZONE_OFFSETS[zone]; int dayOffset = selection / (24 * 60); int hourOffset = selection % (24 * 60 ) / 60; int minuteOffset = selection % 60; long today = System.currentTimeMillis(); today = today - (today % (24 * 60 * 60000)) + (dayOffset * 60000 * 60 * 24) + (hourOffset * 60000 * 60) + (minuteOffset * 60000); cal.setTime(new Date(today)); int hour = cal.get(java.util.Calendar.HOUR_OF_DAY); int minute = cal.get(java.util.Calendar.MINUTE); int dow = cal.get(java.util.Calendar.DAY_OF_WEEK); int dom = cal.get(java.util.Calendar.DAY_OF_MONTH); int month = cal.get(java.util.Calendar.MONTH); Label dayOrNight = findDayOrNight(friend); if(hour > 18 || hour < 7) { dayOrNight.setIcon(moonImage); } else { dayOrNight.setIcon(sunImage); } Label dowLabel = findDayOfWeek(friend); dowLabel.setText(DAYS[dow - 1]); Label dateLabel = findDate(friend); dateLabel.setText(MONTHS[month] + " " + dom); Label timeOfDayLabel = findTimeOfDay(friend); timeOfDayLabel.setText(formatTime(hour, minute)); // not enough room for the labels, clear room for them, we don't revalidate all the time since the performance would suffer if(timeOfDayLabel.shouldTickerStart() || dateLabel.shouldTickerStart() || dowLabel.shouldTickerStart()) { friend.revalidate(); } } private void addHashtable(Form f, final Hashtable h) { addHashtable(f, h, -1); } private void addHashtable(Form f, final Hashtable h, int offset) { Resources res = fetchResourceFile(); final Container friend = createContainer(res, "Friend"); Button remove = findRemoveFriend(friend); remove.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { h.put("selected", "false"); Label empty = new Label(); empty.setPreferredSize(friend.getPreferredSize()); Container parent = friend.getParent(); parent.replaceAndWait(friend, empty, CommonTransitions.createSlide(CommonTransitions.SLIDE_HORIZONTAL, false, 250)); parent.removeComponent(empty); parent.animateLayout(300); } }); if(removeMode) { friend.setFocusable(false); } else { remove.setPreferredSize(new Dimension(0, 0)); } friend.putClientProperty("data", h); Label friendName = findFriendName(friend); friendName.setText((String)h.get("title")); Image picture = (Image)h.get("icon"); if(picture != null) { friendName.setIcon(picture); } else { friendName.setIcon(res.getImage("add_zone_world_icon.png")); } Container root = findFriendsRoot(f); if(offset < 0) { root.addComponent(friend); } else { root.addComponent(offset, friend); } updateFriendTime(friend); } protected boolean initListModelAddZoneList(List cmp) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.initListModelAddZoneList(cmp); if(friendsMode) { cmp.setModel(new DefaultListModel(FRIENDS)); } else { cmp.setModel(new DefaultListModel(TIMEZONE_ENTRIES)); } return true; } protected void onAddZone_WorldZoneAction(Component c, ActionEvent event) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.onAddZone_WorldZoneAction(c, event); friendsMode = false; initListModelAddZoneList(findAddZoneList(c.getParent())); } protected void onAddZone_FriendZoneAction(Component c, ActionEvent event) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.onAddZone_FriendZoneAction(c, event); friendsMode = true; initListModelAddZoneList(findAddZoneList(c.getParent())); } protected void onSettings_CivilianTimeCheckboxAction(Component c, ActionEvent event) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.onSettings_CivilianTimeCheckboxAction(c, event); civilianTime = ((CheckBox)c).isSelected(); } private String formatTime(int hours, int minutes) { if(civilianTime) { if(hours < 12) { if(hours == 0) { return "12:" + twoDigits(minutes) + "AM"; } else { return twoDigits(hours) + ":" + twoDigits(minutes) + "AM"; } } else { return hours + ":" + twoDigits(minutes) + "PM"; } } else { return twoDigits(hours) + ":" + twoDigits(minutes); } } protected void exitSettings(Form f) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.exitSettings(f); // if we have more settings in the future, this is the place to update them } protected void exitAddZone(Form f) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.exitAddZone(f); // the upcoming form is the main form f = Display.getInstance().getCurrent(); Container friendRoot = findFriendsRoot(f); for(int iter = 0 ; iter < friendRoot.getComponentCount() ; iter++) { Component c = friendRoot.getComponentAt(iter); Hashtable friendHash = (Hashtable)c.getClientProperty("data"); if(!"true".equals(friendHash.get("selected"))) { friendRoot.removeComponent(c); } } for(int iter = 0 ; iter < TIMEZONE_ENTRIES.length ; iter++) { String s = (String)TIMEZONE_ENTRIES[iter].get("selected"); if("true".equals(s) && !checkIfAddedAlready(friendRoot, TIMEZONE_ENTRIES[iter])) { addHashtable(f, TIMEZONE_ENTRIES[iter], 0); } } for(int iter = 0 ; iter < FRIENDS.length ; iter++) { String s = (String)FRIENDS[iter].get("selected"); if("true".equals(s) && !checkIfAddedAlready(friendRoot, FRIENDS[iter])) { addHashtable(f, FRIENDS[iter], 0); } } updateTimes(f); friendRoot.animateLayout(1200); } private boolean checkIfAddedAlready(Container friendRoot, Object friendKey) { for(int iter = 0 ; iter < friendRoot.getComponentCount() ; iter++) { Component c = friendRoot.getComponentAt(iter); Hashtable friendHash = (Hashtable)c.getClientProperty("data"); if(friendHash == friendKey) { return true; } } return false; } protected void beforeSettings(Form f) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.beforeSettings(f); findCivilianTimeCheckbox(f).setSelected(civilianTime); } protected void onMainUI_RemoveModeButtonAction(Component c, ActionEvent event) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.onMainUI_RemoveModeButtonAction(c, event); removeMode = !removeMode; Container friendRoot = findFriendsRoot(c.getParent()); Dimension size = null; if(removeMode) { if(Display.getInstance().getDeviceDensity() > Display.DENSITY_LOW) { findRemoveModeButton(c.getParent()).setText("Finish"); } } else { size = new Dimension(0, 0); if(Display.getInstance().getDeviceDensity() > Display.DENSITY_LOW) { findRemoveModeButton(c.getParent()).setText("Remove"); } } for(int iter = 0 ; iter < friendRoot.getComponentCount() ; iter++) { Container currentFriend = (Container)friendRoot.getComponentAt(iter); currentFriend.setShouldCalcPreferredSize(true); currentFriend.setFocusable(!removeMode); findRemoveFriend(currentFriend).setPreferredSize(size); currentFriend.animateLayout(800); } } private Container splashTitle; private Label dummyTitle; protected void beforeSplash(Form f) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.beforeSplash(f); splashTitle = findTitleArea(f); // create a "slide in" effect for the title dummyTitle = new Label(); dummyTitle.setPreferredSize(splashTitle.getPreferredSize()); f.replace(splashTitle, dummyTitle, null); } protected void postSplash(Form f) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.postSplash(f); f.replace(dummyTitle, splashTitle, CommonTransitions.createSlide(CommonTransitions.SLIDE_VERTICAL, true, 1000)); splashTitle = null; dummyTitle = null; } }