001: package net.xoetrope.xui;
002:
003: import java.util.Hashtable;
004: import java.util.Stack;
005:
006: import java.awt.Container;
007:
008: import net.xoetrope.debug.DebugLogger;
009: import net.xoetrope.xui.build.BuildProperties;
010: import java.awt.Component;
011:
012: /**
013: * A class for loading and displaying XPages. This class manages access to
014: * individual pages and coordinates update of the dispaly area. Pages can also be
015: * displayed as part of a frameset. The page manager caches the pages to improve
016: * performance and maintain state.
017: * <p>Copyright (c) Xoetrope Ltd., 2002-2003</p>
018: * <p>License: see license.txt</p>
019: * $Revision: 1.26 $
020: */
021: public class XPageManager {
022: protected Hashtable pages;
023: protected String packageName;
024: protected Stack pageHistory;
025:
026: protected XPageDisplay pageDisplay;
027: protected XPageLoader secondaryLoader;
028:
029: /**
030: * Constructor which creates a hastable to store the pages
031: */
032: public XPageManager() {
033: reset();
034: }
035:
036: /**
037: * Set the package name.
038: * @param pkgName the name of the package we're running from.
039: */
040: public void setPackageName(String pkgName) {
041: packageName = pkgName;
042: }
043:
044: /**
045: * Set the interface to invoke when a page has been displayed.
046: * Reads the startup parameters Frames and UsesFrames to control loading of
047: * the frame set. If Frames is not specified it defaults to "frames", and if
048: * UsesFrames is not specified it defaults to "true".
049: * @param pgDisplay The XPageDisplay interface
050: */
051: public void setPageDisplay(XPageDisplay pgDisplay) {
052: pageDisplay = pgDisplay;
053: String framesetName = null;
054: String loadFrameset = null;
055: try {
056: framesetName = XProjectManager.getCurrentProject()
057: .getStartupParam("Frames");
058: loadFrameset = XProjectManager.getCurrentProject()
059: .getStartupParam("UseFrames");
060: } catch (Exception ex) {
061: } finally {
062: if (framesetName == null)
063: framesetName = "frames";
064: if (loadFrameset == null)
065: loadFrameset = "true";
066: }
067: if (loadFrameset.equals("true"))
068: loadFrames(framesetName);
069: }
070:
071: /**
072: * Load a page. Check first to see if we have it in the Hashtable
073: * @param className the name of the class we want to load.
074: */
075: public XPage loadPage(String className) {
076: return loadPage(className, true);
077: }
078:
079: /**
080: * Load a page. Check first to see if we have it in the Hashtable when the
081: * cache flag is set to true.
082: * @param className the name of the class we want to load.
083: * @param cache whether or not to cache the page or check the cache
084: * @return the cached page or the newly created page.
085: */
086: public XPage loadPage(String className, boolean cache) {
087: XPage newPage = null;
088: if (cache)
089: newPage = (XPage) pages.get(packageName + className);
090: if (newPage == null) {
091: // Try loading the XML description first
092: if (secondaryLoader != null) {
093: newPage = secondaryLoader.loadPage(packageName,
094: className, false);
095: if ((newPage != null) && cache)
096: pages.put(packageName + className, newPage);
097: }
098:
099: // if that doesn't load a page then try and find a class description
100: if (newPage == null) {
101: try {
102: String pageName;
103: if ((packageName != null)
104: && (packageName.length() > 1))
105: pageName = packageName + className;
106: else
107: pageName = className;
108:
109: newPage = (XPage) Class.forName(pageName)
110: .newInstance();
111: } catch (Exception e) {
112: DebugLogger.logError("Unable to create the page: "
113: + packageName + className);
114: if (BuildProperties.DEBUG)
115: e.printStackTrace();
116: newPage = new XPage();
117: }
118: if (cache)
119: pages.put(packageName + className, newPage);
120: }
121: newPage.setName(className);
122: newPage.setStatus(XPage.CREATED);
123:
124: try {
125: newPage.pageCreated();
126: } catch (Exception ex) {
127: if (BuildProperties.DEBUG) {
128: DebugLogger
129: .logError("The pageCreated method could not be invoked due to an exception");
130: ex.printStackTrace();
131: }
132: }
133: }
134:
135: return newPage;
136: }
137:
138: /**
139: * Loads a frameset. Check first to see if we have it in the Hashtable
140: * @param frameSetName the name of the frameSet we want to load.
141: */
142: public void loadFrames(String frameSetName) {
143: if (secondaryLoader != null)
144: secondaryLoader.loadFrames(packageName, frameSetName,
145: pageDisplay);
146: }
147:
148: /**
149: * Return the instance. This class now delegates to the project manager.
150: * @deprecated since 1.0.3 use XProjectManager.getCurrentProject().getPageManager() or XProjectManager.getPageManager()
151: */
152: public XPageManager getInstance() {
153: return XProjectManager.getCurrentProject().getPageManager();
154: }
155:
156: /**
157: * Get a page
158: * @param className the page name
159: * @return the page or else null if the page hasn't been loaded yet.
160: */
161: public XPage getPage(String className) {
162: return (XPage) pages.get(packageName + className);
163: }
164:
165: /**
166: * Get the page currently displayed by a particular target container
167: * @param target the target container name
168: * @return the page or else null if the page hasn't been loaded yet.
169: */
170: public XPage getCurrentPage(String target) {
171: Component c = getTarget(target).getComponent(0);
172: if (c instanceof XPage)
173: return (XPage) getTarget(target).getComponent(0);
174:
175: // There is possibly a tooltip as component 0
176: return (XPage) getTarget(target).getComponent(1);
177: }
178:
179: /**
180: * Get the page previously displayed by the 'content' target container
181: * @return the page or else null if there wasn't a previous page
182: */
183: public XPage getPreviousPage() {
184: // This assumes that the stack is LIFO and appends at the end of its array
185: // as of java.util.Stack v1.25
186: int historyLen = pageHistory.size();
187: if (historyLen > 1)
188: return (XPage) getPage((String) pageHistory
189: .elementAt(historyLen - 2));
190:
191: return null;
192: }
193:
194: /**
195: * Load and show a page.
196: * @param className
197: * @return the page being displayed
198: */
199: public XPage showPage(String className) {
200: return showPage(className, null);
201: }
202:
203: /**
204: * Load and show a page.
205: * @param className
206: * @param target the area to update
207: * @return the page being displayed
208: */
209: public XPage showPage(String className, String target) {
210: XPage page = loadPage(className);
211: if (page == null)
212: page = loadPage("ErrorPage");
213: else
214: pageHistory.push(className);
215:
216: return pageDisplay.displayPage(page, target);
217: }
218:
219: /**
220: * Show the previously displayed page.
221: */
222: public XPage showPrevious() {
223: // Pop this page. If its the first page we need to keep the entry because
224: // we cannot navigate beyond it.
225: if (pageHistory.size() > 1)
226: pageHistory.pop();
227:
228: if (!pageHistory.empty()) {
229: try {
230: // Now get the name of the previous page.
231: String className = (String) pageHistory.peek();
232: if (className != null) {
233: XPage page = loadPage(className);
234: pageDisplay.displayPage(page);
235: return page;
236: }
237: } catch (Exception ex) {
238: ex.printStackTrace();
239: }
240: }
241: return null;
242: }
243:
244: /**
245: * Set the page loader class. XuiBuilder is an example of a secondary page
246: * loader that loads pages from an XML description.
247: * @param pl the page loader instance
248: */
249: public void setSecondaryLoader(XPageLoader pl) {
250: secondaryLoader = pl;
251: }
252:
253: /**
254: * Get a named frame/target from the current frameset
255: * @param name the name of the frame
256: * @return the target frame
257: */
258: public Container getTarget(String name) {
259: return pageDisplay.findTarget(name);
260: }
261:
262: /**
263: * Get the number of frame/target from the current frameset
264: * @return the number of target frames
265: */
266: public int getNumTargets() {
267: return pageDisplay.getNumTargets();
268: }
269:
270: /**
271: * Get the target for a page display request
272: * @param idx the target area
273: * @return the container to be updated
274: */
275: public Container getTarget(int idx) {
276: return pageDisplay.getTarget(idx);
277: }
278:
279: public void addHistory(String className) {
280: pageHistory.push(className);
281: }
282:
283: /**
284: * Reset the page history and dump any loaded pages.
285: */
286: public void reset() {
287: pages = new Hashtable(3);
288: pageHistory = new Stack();
289: }
290: }
|