001: /*******************************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *******************************************************************************/package org.ofbiz.pos.screen;
019:
020: import java.awt.AWTEvent;
021: import java.awt.Frame;
022: import java.awt.Window;
023: import java.awt.event.FocusEvent;
024: import java.awt.event.FocusListener;
025:
026: import java.util.*;
027:
028: import net.xoetrope.builder.NavigationHelper;
029: import net.xoetrope.xui.XPage;
030: import net.xoetrope.xui.XProjectManager;
031:
032: import org.ofbiz.base.splash.SplashLoader;
033: import org.ofbiz.base.util.Debug;
034: import org.ofbiz.base.util.UtilFormatOut;
035: import org.ofbiz.base.util.UtilProperties;
036: import org.ofbiz.guiapp.xui.XuiContainer;
037: import org.ofbiz.guiapp.xui.XuiSession;
038: import org.ofbiz.pos.PosTransaction;
039: import org.ofbiz.pos.adaptor.KeyboardAdaptor;
040: import org.ofbiz.pos.component.InputWithPassword;
041: import org.ofbiz.pos.component.Journal;
042: import org.ofbiz.pos.component.Operator;
043: import org.ofbiz.pos.component.Output;
044: import org.ofbiz.pos.component.PosButton;
045: import org.ofbiz.pos.device.DeviceLoader;
046:
047: public class PosScreen extends NavigationHelper implements Runnable,
048: DialogCallback, FocusListener {
049:
050: public static final String module = PosScreen.class.getName();
051: public static final Frame appFrame = XProjectManager
052: .getCurrentProject().getAppFrame();
053: public static final Window appWin = XProjectManager
054: .getCurrentProject().getAppWindow();
055: public static final String BUTTON_ACTION_METHOD = "buttonPressed";
056: public static final long MAX_INACTIVITY = 1800000;
057: public static PosScreen currentScreen;
058:
059: protected static boolean monitorRunning = false;
060: protected static boolean firstInit = false;
061: protected static long lastActivity = 0;
062: protected static Thread activityMonitor = null;
063:
064: protected ClassLoader classLoader = null;
065: protected XuiSession session = null;
066: protected Output output = null;
067: protected InputWithPassword input = null;
068: protected Journal journal = null;
069: protected Operator operator = null;
070: protected PosButton buttons = null;
071: protected String scrLocation = null;
072: protected boolean isLocked = false;
073: protected boolean inDialog = false;
074:
075: private Locale defaultLocale = Locale.getDefault();
076:
077: public PosScreen() {
078: super ();
079: this .classLoader = Thread.currentThread()
080: .getContextClassLoader();
081: this .addFocusListener(this );
082: }
083:
084: public void pageCreated() {
085: super .pageCreated();
086:
087: // initial settings
088: this .setEnabled(false);
089: this .setVisible(false);
090:
091: // setup the shared components
092: this .session = XuiContainer.getSession();
093: this .output = new Output(this );
094: this .input = new InputWithPassword(this );
095: this .journal = new Journal(this );
096: this .operator = new Operator(this );
097: this .setLastActivity(System.currentTimeMillis());
098:
099: if (!firstInit) {
100: firstInit = true;
101:
102: // pre-load a few screens
103: XProjectManager.getPageManager().loadPage(
104: this .getScreenLocation() + "/paypanel");
105: XProjectManager.getPageManager().loadPage(
106: this .getScreenLocation() + "/mgrpanel");
107: XProjectManager.getPageManager().loadPage(
108: this .getScreenLocation() + "/promopanel");
109:
110: // start the shared monitor thread
111: if (activityMonitor == null) {
112: monitorRunning = true;
113: activityMonitor = new Thread(this );
114: activityMonitor.setDaemon(false);
115: activityMonitor.start();
116: }
117:
118: // configure the window listener
119: KeyboardAdaptor.attachComponents(appWin, false);
120: appFrame.addFocusListener(this );
121: appWin.addFocusListener(this );
122:
123: // close the splash screen
124: SplashLoader.close();
125: }
126:
127: // buttons are different per screen
128: this .buttons = new PosButton(this );
129:
130: // make sure all components have the keyboard set
131: KeyboardAdaptor.attachComponents(this );
132: }
133:
134: public void pageActivated() {
135: super .pageActivated();
136:
137: this .setLastActivity(System.currentTimeMillis());
138:
139: if (session.getUserLogin() == null) {
140: this .setLock(true);
141: } else {
142: this .setLock(isLocked);
143: }
144:
145: currentScreen = this ;
146: this .refresh();
147: }
148:
149: public void pageDeactivated() {
150: super .pageDeactivated();
151:
152: if (Debug.verboseOn()) {
153: this .logInfo();
154: }
155: }
156:
157: public void logInfo() {
158: Debug.log("App Frame :", module);
159: Debug.log("name - " + appFrame.getName(), module);
160: Debug.log("title - " + appFrame.getTitle(), module);
161: Debug.log("active - " + appFrame.isActive(), module);
162: Debug.log("enabled - " + appFrame.isEnabled(), module);
163: Debug.log("visible - " + appFrame.isVisible(), module);
164: Debug.log("showing - " + appFrame.isShowing(), module);
165: Debug.log("opaque - " + appFrame.isOpaque(), module);
166: Debug.log("focusable - " + appFrame.isFocusable(), module);
167: Debug.log("focused - " + appFrame.isFocused(), module);
168: Debug.log("hasFocus - " + appFrame.hasFocus(), module);
169:
170: Debug.log("", module);
171: Debug.log("App Window :", module);
172: Debug.log("name - " + appWin.getName(), module);
173: Debug.log("active - " + appWin.isActive(), module);
174: Debug.log("enabled - " + appWin.isEnabled(), module);
175: Debug.log("visible - " + appWin.isVisible(), module);
176: Debug.log("showing - " + appWin.isShowing(), module);
177: Debug.log("opaque - " + appWin.isOpaque(), module);
178: Debug.log("focusable - " + appWin.isFocusable(), module);
179: Debug.log("focused - " + appWin.isFocused(), module);
180: Debug.log("hasFocus - " + appWin.hasFocus(), module);
181:
182: Debug.log("", module);
183:
184: Debug.log("POS Screen :", module);
185: Debug.log("name - " + this .getName(), module);
186: Debug.log("enabled - " + this .isEnabled(), module);
187: Debug.log("visible - " + this .isVisible(), module);
188: Debug.log("showing - " + this .isShowing(), module);
189: Debug.log("opaque - " + this .isOpaque(), module);
190: Debug.log("focusable - " + this .isFocusable(), module);
191: Debug.log("focused - " + this .hasFocus(), module);
192: }
193:
194: public void refresh() {
195: this .refresh(true);
196: }
197:
198: public void refresh(boolean updateOutput) {
199: PosTransaction trans = PosTransaction.getCurrentTx(this
200: .getSession());
201: if (trans == null) {
202: updateOutput = false;
203: }
204:
205: appFrame.requestFocus();
206: this .lockScreenButton(this );
207: //this.requestFocus();
208:
209: if (!isLocked) {
210: this .setEnabled(true);
211: this .setVisible(true);
212: journal.refresh(this );
213: input.clearInput();
214: operator.refresh();
215: if (updateOutput) {
216: if (input.isFunctionSet("PAID")) {
217: output.print(UtilProperties.getMessage("pos",
218: "CHANGE", defaultLocale)
219: + UtilFormatOut.formatPrice(trans
220: .getTotalDue()
221: * -1));
222: } else if (input.isFunctionSet("TOTAL")) {
223: if (trans.getTotalDue() > 0) {
224: output.print(UtilProperties.getMessage("pos",
225: "TOTALD", defaultLocale)
226: + " "
227: + UtilFormatOut.formatPrice(trans
228: .getTotalDue()));
229: } else {
230: output.print(UtilProperties.getMessage("pos",
231: "PAYFIN", defaultLocale));
232: }
233: } else {
234: if (PosTransaction.getCurrentTx(session).isOpen()) {
235: output.print(UtilProperties.getMessage("pos",
236: "ISOPEN", defaultLocale));
237: } else {
238: output.print(UtilProperties.getMessage("pos",
239: "ISCLOSED", defaultLocale));
240: }
241: }
242: }
243: //journal.focus();
244: } else {
245: output.print(UtilProperties.getMessage("pos", "ULOGIN",
246: defaultLocale));
247: //input.focus();
248: }
249:
250: this .repaint();
251: //this.logInfo();
252: }
253:
254: public boolean isLocked() {
255: return isLocked;
256: }
257:
258: public void setLock(boolean lock) {
259: this .buttons.setLock(lock);
260: this .input.setLock(lock);
261: this .output.setLock(lock);
262: this .journal.setLock(lock);
263: this .operator.setLock(lock);
264: this .isLocked = lock;
265: if (lock) {
266: this .input.setFunction("LOGIN");
267: }
268: DeviceLoader.enable(!lock);
269: }
270:
271: public XuiSession getSession() {
272: return this .session;
273: }
274:
275: public InputWithPassword getInput() {
276: return this .input;
277: }
278:
279: public Output getOutput() {
280: return this .output;
281: }
282:
283: public Journal getJournal() {
284: return this .journal;
285: }
286:
287: public PosButton getButtons() {
288: return this .buttons;
289: }
290:
291: public void setLastActivity(long l) {
292: lastActivity = l;
293: }
294:
295: public ClassLoader getClassLoader() {
296: return classLoader;
297: }
298:
299: // generic button XUI event calls into PosButton to lookup the external reference
300: public synchronized void buttonPressed() {
301: this .setLastActivity(System.currentTimeMillis());
302: buttons.buttonPressed(this , (AWTEvent) this .getCurrentEvent());
303: journal.focus();
304: }
305:
306: // generic page display methods - extends those in XPage
307: public PosScreen showPage(String pageName) {
308: return this .showPage(pageName, true);
309: }
310:
311: public PosScreen showPage(String pageName, boolean refresh) {
312: if (pageName.startsWith("/")) {
313: pageName = pageName.substring(1);
314: }
315: XPage newPage = (XPage) XProjectManager.getPageManager()
316: .showPage(this .getScreenLocation() + "/" + pageName);
317: if (newPage instanceof PosScreen) {
318: if (refresh)
319: ((PosScreen) newPage).refresh();
320: return (PosScreen) newPage;
321: }
322: return null;
323: }
324:
325: public void lockScreenButton(PosScreen pos) {
326: if ((this .getScreenLocation() + "/pospanel").equals(pos
327: .getName())) {
328: pos.getButtons().setLock("menuMain", true);
329: } else if ((this .getScreenLocation() + "/mgrpanel").equals(pos
330: .getName())) {
331: pos.getButtons().setLock("menuMgr", true);
332: } else if ((this .getScreenLocation() + "/paypanel").equals(pos
333: .getName())) {
334: pos.getButtons().setLock("menuPay", true);
335: } else if ((this .getScreenLocation() + "/promopanel")
336: .equals(pos.getName())) {
337: pos.getButtons().setLock("menuPromo", true);
338: }
339: }
340:
341: public PosDialog showDialog(String pageName) {
342: return showDialog(pageName, this , null);
343: }
344:
345: public PosDialog showDialog(String pageName, String text) {
346: return showDialog(pageName, this , text);
347: }
348:
349: public PosDialog showDialog(String pageName, DialogCallback cb) {
350: return showDialog(pageName, cb, null);
351: }
352:
353: public PosDialog showDialog(String pageName, DialogCallback cb,
354: String text) {
355: if (pageName.startsWith("/")) {
356: pageName = pageName.substring(1);
357: }
358: XPage dialogPage = (XPage) XProjectManager.getPageManager()
359: .loadPage(this .getScreenLocation() + "/" + pageName);
360: PosDialog dialog = PosDialog.getInstance(dialogPage, true, 0);
361: dialog.showDialog(this , cb, text);
362: return dialog;
363: }
364:
365: // PosDialog Callback method
366: public void receiveDialogCb(PosDialog dialog) {
367: Debug.log("Dialog closed; refreshing screen", module);
368: this .refresh();
369: }
370:
371: // run method for auto-locking POS on inactivity
372: public void run() {
373: while (monitorRunning) {
374: if (!isLocked
375: && (System.currentTimeMillis() - lastActivity) > MAX_INACTIVITY) {
376: Debug.log("POS terminal auto-lock activated", module);
377: PosScreen.currentScreen.showPage("pospanel").setLock(
378: true);
379: }
380: try {
381: Thread.sleep(5000);
382: } catch (InterruptedException e) {
383: Debug.logError(e, module);
384: }
385: }
386: }
387:
388: public void focusGained(FocusEvent event) {
389: if (Debug.verboseOn()) {
390: String from = event != null
391: && event.getOppositeComponent() != null ? event
392: .getOppositeComponent().getName() : "??";
393: Debug.log(event.getSource() + " focus gained from " + from,
394: module);
395: }
396: }
397:
398: public void focusLost(FocusEvent event) {
399: if (Debug.verboseOn()) {
400: String to = event != null
401: && event.getOppositeComponent() != null ? event
402: .getOppositeComponent().getName() : "??";
403: Debug.log(event.getSource() + " focus lost to " + to,
404: module);
405: }
406: }
407:
408: public String getScreenLocation() {
409: if (this .scrLocation == null) {
410: synchronized (this ) {
411: if (this .scrLocation == null) {
412: String xuiProps = this .getSession().getContainer()
413: .getXuiPropertiesName();
414: String startClass = UtilProperties
415: .getPropertyValue(xuiProps, "StartClass",
416: "default/pospanel");
417: this .scrLocation = startClass.substring(0,
418: startClass.indexOf("/"));
419: }
420: }
421: }
422: return this .scrLocation;
423: }
424:
425: public void setWaitCursor() {
426: setCursor(java.awt.Cursor
427: .getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR));
428: }
429:
430: public void setNormalCursor() {
431: setCursor(java.awt.Cursor
432: .getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
433: }
434: }
|