You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ThemeFunctionLibrary.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. /* *************************************************************************
  2. IT Mill Toolkit
  3. Development of Browser User Intarfaces Made Easy
  4. Copyright (C) 2000-2006 IT Mill Ltd
  5. *************************************************************************
  6. This product is distributed under commercial license that can be found
  7. from the product package on license/license.txt. Use of this product might
  8. require purchasing a commercial license from IT Mill Ltd. For guidelines
  9. on usage, see license/licensing-guidelines.html
  10. *************************************************************************
  11. For more information, contact:
  12. IT Mill Ltd phone: +358 2 4802 7180
  13. Ruukinkatu 2-4 fax: +358 2 4802 7181
  14. 20540, Turku email: info@itmill.com
  15. Finland company www: www.itmill.com
  16. Primary source for information and releases: www.itmill.com
  17. ********************************************************************** */
  18. package com.itmill.toolkit.terminal.web;
  19. import com.itmill.toolkit.Application;
  20. import com.itmill.toolkit.terminal.ThemeResource;
  21. import com.itmill.toolkit.ui.FrameWindow;
  22. import com.itmill.toolkit.ui.Window;
  23. import java.text.DateFormatSymbols;
  24. import java.util.Calendar;
  25. import java.util.Collection;
  26. import java.util.GregorianCalendar;
  27. import java.util.Iterator;
  28. import java.util.LinkedList;
  29. import java.util.Set;
  30. import javax.servlet.http.HttpSession;
  31. /**
  32. * This a function library that can be used from the theme XSL-files. It
  33. * provides easy access to current application, window, theme, webbrowser and
  34. * session. The internal threadlocal state must be maintained by the webadapter
  35. * in order go guarantee that it works.
  36. *
  37. * @author IT Mill Ltd.
  38. * @version
  39. * @VERSION@
  40. * @since 3.0
  41. */
  42. public class ThemeFunctionLibrary {
  43. static private final int APPLICATION = 0;
  44. static private final int WINDOW = 1;
  45. static private final int WEBBROWSER = 2;
  46. static private final int SESSION = 3;
  47. static private final int WEBADAPTERSERVLET = 4;
  48. static private final int THEME = 5;
  49. static private ThreadLocal state = new ThreadLocal();
  50. static protected void setState(Application application, Window window,
  51. WebBrowser webBrowser, HttpSession session,
  52. ApplicationServlet webAdapterServlet, String theme) {
  53. state.set(new Object[] { application, window, webBrowser, session,
  54. webAdapterServlet, theme });
  55. }
  56. static protected void cleanState() {
  57. state.set(null);
  58. }
  59. /**
  60. * Returns a reference to the application object associated with the session
  61. * that the call came from.
  62. */
  63. static public Application application() {
  64. try {
  65. return (Application) ((Object[]) state.get())[APPLICATION];
  66. } catch (NullPointerException e) {
  67. throw new IllegalStateException();
  68. }
  69. }
  70. /**
  71. * Returns a reference to the current window object associated with the
  72. * session that the call came from.
  73. */
  74. static public Window window() {
  75. try {
  76. return (Window) ((Object[]) state.get())[WINDOW];
  77. } catch (NullPointerException e) {
  78. throw new IllegalStateException();
  79. }
  80. }
  81. /**
  82. * Returns a reference to the browser object associated with the session
  83. * that the call came from.
  84. */
  85. static public WebBrowser browser() {
  86. try {
  87. return (WebBrowser) ((Object[]) state.get())[WEBBROWSER];
  88. } catch (NullPointerException e) {
  89. throw new IllegalStateException();
  90. }
  91. }
  92. /**
  93. * Returns a reference to the current servlet http session object that is
  94. * associated with the session that the call came from.
  95. */
  96. static public HttpSession session() {
  97. try {
  98. return (HttpSession) ((Object[]) state.get())[SESSION];
  99. } catch (NullPointerException e) {
  100. throw new IllegalStateException();
  101. }
  102. }
  103. /**
  104. * Return a reference to the current theme name that is associated with the
  105. * session that the call came from.
  106. */
  107. static public String theme() {
  108. try {
  109. return (String) ((Object[]) state.get())[THEME];
  110. } catch (NullPointerException e) {
  111. throw new IllegalStateException();
  112. }
  113. }
  114. /**
  115. * Return an URI to the named resource from the named theme.
  116. */
  117. static public String resource(String resource, String theme) {
  118. try {
  119. return ((ApplicationServlet) ((Object[]) state.get())[WEBADAPTERSERVLET])
  120. .getResourceLocation(theme, new ThemeResource(resource));
  121. } catch (NullPointerException e) {
  122. throw new IllegalStateException();
  123. }
  124. }
  125. /**
  126. * Return an URI to the named resource.
  127. */
  128. static public String resource(String resource) {
  129. try {
  130. return ((ApplicationServlet) ((Object[]) state.get())[WEBADAPTERSERVLET])
  131. .getResourceLocation(theme(), new ThemeResource(resource));
  132. } catch (NullPointerException e) {
  133. throw new IllegalStateException();
  134. }
  135. }
  136. /**
  137. * Generate JavaScript for page that performs client-side combility checks.
  138. */
  139. static public boolean probeClient() {
  140. return (browser().performClientCheck() && !browser()
  141. .isClientSideChecked());
  142. }
  143. /**
  144. * Generate JavaScript for page header that handles window refreshing,
  145. * opening and closing.
  146. *
  147. * Generates script that:
  148. * <ul>
  149. * <li>Requests that all windows that need repaint be reloaded</li>
  150. * <li>Sets the window name</li>
  151. * <li>Closes window if it is set to be closed </li>
  152. * <ul>
  153. *
  154. */
  155. static public String windowScript() {
  156. return generateWindowScript(
  157. window(),
  158. application(),
  159. (ApplicationServlet) ((Object[]) state.get())[WEBADAPTERSERVLET],
  160. browser());
  161. }
  162. static protected String generateWindowScript(Window window,
  163. Application app, ApplicationServlet wa, WebBrowser browser) {
  164. StringBuffer script = new StringBuffer();
  165. LinkedList update = new LinkedList();
  166. // Add all the windows needto update list
  167. Set dirtyWindows = wa != null ? wa.getDirtyWindows(app) : null;
  168. if (dirtyWindows != null)
  169. for (Iterator i = dirtyWindows.iterator(); i.hasNext();) {
  170. Window w = (Window) i.next();
  171. if (w != window) {
  172. if (w instanceof FrameWindow)
  173. update.addFirst(w);
  174. else
  175. update.addLast(w);
  176. }
  177. }
  178. // Remove all windows that are in frames, of such frame windows that
  179. // will be updated anyway
  180. Object[] u = update.toArray();
  181. if (u.length > 0 && (window != null && window instanceof FrameWindow))
  182. u[u.length - 1] = window;
  183. for (int i = 0; i < u.length; i++) {
  184. try {
  185. FrameWindow w = (FrameWindow) u[i];
  186. LinkedList framesets = new LinkedList();
  187. framesets.add(w.getFrameset());
  188. while (!framesets.isEmpty()) {
  189. FrameWindow.Frameset fs = (FrameWindow.Frameset) framesets
  190. .removeFirst();
  191. for (Iterator j = fs.getFrames().iterator(); j.hasNext();) {
  192. FrameWindow.Frame f = (FrameWindow.Frame) j.next();
  193. if (f instanceof FrameWindow.Frameset)
  194. framesets.add(f);
  195. else if (f.getWindow() != null) {
  196. update.remove(f.getWindow());
  197. wa.removeDirtyWindow(app, f.getWindow());
  198. }
  199. }
  200. }
  201. } catch (ClassCastException ignored) {
  202. }
  203. }
  204. // Set window name
  205. if (window != null) {
  206. script.append("window.name = \"" + getWindowTargetName(app, window)
  207. + "\";\n");
  208. }
  209. // Generate window updatescript
  210. for (Iterator i = update.iterator(); i.hasNext();) {
  211. Window w = (Window) i.next();
  212. script.append(getWindowRefreshScript(app, w, browser));
  213. wa.removeDirtyWindow(app, w);
  214. // Windows that are closed immediately are "painted" now
  215. if (w.getApplication() == null || !w.isVisible())
  216. w.requestRepaintRequests();
  217. }
  218. // Close current window if it is not visible
  219. if (window == null || !window.isVisible())
  220. script.append("window.close();\n");
  221. return script.toString();
  222. }
  223. /**
  224. * Returns an unique target name for a given window name.
  225. *
  226. * @param windowName
  227. * Name of the window.
  228. * @return An unique ID for window target
  229. * @throws IllegalStateException
  230. * If application for window is null.
  231. */
  232. static public String getWindowTargetName(Application application,
  233. Window window) {
  234. try {
  235. return "" + application.hashCode() + "_" + window.getName();
  236. } catch (NullPointerException e) {
  237. throw new IllegalStateException();
  238. }
  239. }
  240. /**
  241. * Returns an unique target name for current window.
  242. *
  243. * @return An unique ID for window target
  244. */
  245. static public String getWindowTargetName() {
  246. return getWindowTargetName(application(), window());
  247. }
  248. /**
  249. * Returns an unique target name for current window.
  250. *
  251. * @return An unique ID for window target
  252. * @throws IllegalStateException
  253. * If application for window is null.
  254. */
  255. static public String getWindowTargetName(String name) {
  256. Window w = application().getWindow(name);
  257. if (w != null)
  258. return getWindowTargetName(application(), w);
  259. else
  260. return name;
  261. }
  262. /* Static mapping for 0 to be sunday. */
  263. private static int[] weekdays = new int[] { Calendar.SUNDAY,
  264. Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY,
  265. Calendar.THURSDAY, Calendar.FRIDAY, Calendar.SATURDAY };
  266. /**
  267. * Returns the country and region code for current application locale.
  268. *
  269. * @see Locale#getCountry()
  270. * @return language Country code of the current application locale.
  271. */
  272. static public String getLocaleCountryId() {
  273. try {
  274. Application app = (Application) ((Object[]) state.get())[APPLICATION];
  275. return app.getLocale().getCountry();
  276. } catch (NullPointerException e) {
  277. throw new IllegalStateException();
  278. }
  279. }
  280. /**
  281. * Returns the language code for current application locale.
  282. *
  283. * @see Locale#getLanguage()
  284. * @return language Language code for current application locale.
  285. */
  286. static public String getLocaleLanguageId() {
  287. try {
  288. Application app = (Application) ((Object[]) state.get())[APPLICATION];
  289. return app.getLocale().getLanguage();
  290. } catch (NullPointerException e) {
  291. throw new IllegalStateException();
  292. }
  293. }
  294. /**
  295. * Get name for week day.
  296. *
  297. * @param Number
  298. * of week day. 0 first day of week.
  299. * @return Name of week day in applications current locale.
  300. */
  301. static public int getFirstDayOfWeek() {
  302. try {
  303. Application app = (Application) ((Object[]) state.get())[APPLICATION];
  304. Calendar cal = new GregorianCalendar(app.getLocale());
  305. int first = cal.getFirstDayOfWeek();
  306. for (int i = 0; i < 7; i++) {
  307. if (first == weekdays[i])
  308. return i;
  309. }
  310. return 0; // default to sunday
  311. } catch (NullPointerException e) {
  312. throw new IllegalStateException();
  313. }
  314. }
  315. /**
  316. * Get name for week day.
  317. *
  318. * @param Number
  319. * of week day. 0 sunday, 1 monday, ...
  320. * @return Name of week day in applications current locale.
  321. */
  322. static public String getShortWeekday(int dayOfWeek) {
  323. try {
  324. Application app = (Application) ((Object[]) state.get())[APPLICATION];
  325. DateFormatSymbols df = new DateFormatSymbols(app.getLocale());
  326. return df.getShortWeekdays()[weekdays[dayOfWeek]];
  327. } catch (NullPointerException e) {
  328. throw new IllegalStateException();
  329. }
  330. }
  331. /**
  332. * Get short name for month.
  333. *
  334. * @param Number
  335. * of month. 0 is January, 1 is February, and so on.
  336. * @return Name of month in applications current locale.
  337. */
  338. static public String getShortMonth(int month) {
  339. try {
  340. Application app = (Application) ((Object[]) state.get())[APPLICATION];
  341. DateFormatSymbols df = new DateFormatSymbols(app.getLocale());
  342. String monthName = df.getShortMonths()[month];
  343. return monthName;
  344. } catch (NullPointerException e) {
  345. throw new IllegalStateException();
  346. }
  347. }
  348. /**
  349. * Get name for month.
  350. *
  351. * @param Number
  352. * of month. 0 is January, 1 is February, and so on.
  353. * @return Name of month in applications current locale.
  354. */
  355. static public String getMonth(int month) {
  356. try {
  357. Application app = (Application) ((Object[]) state.get())[APPLICATION];
  358. DateFormatSymbols df = new DateFormatSymbols(app.getLocale());
  359. String monthName = df.getMonths()[month];
  360. return monthName;
  361. } catch (NullPointerException e) {
  362. throw new IllegalStateException();
  363. }
  364. }
  365. /**
  366. * Get Form Action URL for the requested window.
  367. *
  368. * <p>
  369. * This returns the action for the window main form. This action can be set
  370. * through WebApplicationContect setWindowFormAction method..
  371. * </p>
  372. *
  373. * @return Form action for the current window.
  374. */
  375. static public String getFormAction() {
  376. Window win = window();
  377. Application app = application();
  378. return ((WebApplicationContext) app.getContext())
  379. .getWindowFormAction(win);
  380. }
  381. /** Generate links for CSS files to be included in html head. */
  382. static public String getCssLinksForHead() {
  383. ApplicationServlet as = (ApplicationServlet) ((Object[]) state.get())[WEBADAPTERSERVLET];
  384. Theme t = as.getThemeSource().getThemeByName(theme());
  385. Collection allFiles = t.getFileNames(browser(), Theme.MODE_XSLT);
  386. StringBuffer links = new StringBuffer();
  387. for (Iterator i = allFiles.iterator(); i.hasNext();) {
  388. String file = (String) i.next();
  389. if (file.endsWith(".css")) {
  390. links
  391. .append("<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\""
  392. + resource(file) + "\"/>\n");
  393. }
  394. }
  395. return links.toString();
  396. }
  397. /** Generate links for JavaScript files to be included in html head. */
  398. static public String getJavaScriptLinksForHead() {
  399. ApplicationServlet as = (ApplicationServlet) ((Object[]) state.get())[WEBADAPTERSERVLET];
  400. Theme t = as.getThemeSource().getThemeByName(theme());
  401. Collection allFiles = t.getFileNames(browser(), Theme.MODE_XSLT);
  402. StringBuffer links = new StringBuffer();
  403. for (Iterator i = allFiles.iterator(); i.hasNext();) {
  404. String file = (String) i.next();
  405. if (file.endsWith(".js")) {
  406. links.append("<SCRIPT LANGUAGE=\"Javascript\" SRC=\""
  407. + resource(file) + "\"></SCRIPT>\n");
  408. }
  409. }
  410. return links.toString();
  411. }
  412. /** Generate JavaScript for updating given window */
  413. static protected String getWindowRefreshScript(Application application,
  414. Window window, WebBrowser browser) {
  415. if (application == null)
  416. return "";
  417. if (window == null)
  418. return "";
  419. if (window == null)
  420. return "";
  421. // If window is closed or hidden
  422. if (window.getApplication() == null || !window.isVisible())
  423. return "win = window.open(\"\",\""
  424. + getWindowTargetName(application, window) + "\");\n "
  425. + "if (win != null) { win.close(); }\n";
  426. String url = window.getURL().toString();
  427. String features = "dependent=yes,";
  428. int width = window.getWidth();
  429. int height = window.getHeight();
  430. if (width >= 0)
  431. features += "width=" + width;
  432. if (height >= 0)
  433. features += ((features.length() > 0) ? "," : "") + "height="
  434. + height;
  435. switch (window.getBorder()) {
  436. case Window.BORDER_NONE:
  437. features += ((features.length() > 0) ? "," : "")
  438. + "toolbar=0,location=0,menubar=0,status=0,resizable=1,scrollbars="
  439. + (window.isScrollable() ? "1" : "0");
  440. break;
  441. case Window.BORDER_MINIMAL:
  442. features += ((features.length() > 0) ? "," : "")
  443. + "toolbar=1,location=0,menubar=0,status=1,resizable=1,scrollbars="
  444. + (window.isScrollable() ? "1" : "0");
  445. break;
  446. case Window.BORDER_DEFAULT:
  447. features += ((features.length() > 0) ? "," : "")
  448. + "toolbar=1,location=1,menubar=1,status=1,resizable=1,scrollbars="
  449. + (window.isScrollable() ? "1" : "0");
  450. break;
  451. }
  452. String script = "win = window.open(\"\",\""
  453. + getWindowTargetName(application, window) + "\",\"" + features
  454. + "\");\n" + "if (win != null) {" + "var form = null;";
  455. if (browser != null
  456. && (browser.getJavaScriptVersion().supports(
  457. WebBrowser.JAVASCRIPT_1_5) || browser
  458. .getJavaScriptVersion()
  459. .supports(WebBrowser.JSCRIPT_1_0))) {
  460. script += "try { form = win.document.forms[\"millstone\"];"
  461. + "} catch (e) { form = null;}";
  462. } else {
  463. script += "form = win.document.forms[\"millstone\"];";
  464. }
  465. script += "if (form != null) {" + "form.submit();"
  466. + "} else {win.location.href = \"" + url + "\";}}";
  467. return script;
  468. }
  469. }