| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| *******************************************************************************/ |
| package org.ofbiz.pos.screen; |
| |
| |
| import java.awt.AWTEvent; |
| import java.awt.Frame; |
| import java.awt.Window; |
| import java.awt.event.FocusEvent; |
| import java.awt.event.FocusListener; |
| import java.math.BigDecimal; |
| import java.util.Locale; |
| |
| import net.xoetrope.xui.XPage; |
| import net.xoetrope.xui.XProject; |
| import net.xoetrope.xui.XProjectManager; |
| |
| import org.ofbiz.base.splash.SplashLoader; |
| import org.ofbiz.base.util.Debug; |
| import org.ofbiz.base.util.UtilFormatOut; |
| import org.ofbiz.base.util.UtilProperties; |
| import org.ofbiz.guiapp.xui.XuiContainer; |
| import org.ofbiz.guiapp.xui.XuiSession; |
| import org.ofbiz.pos.PosTransaction; |
| import org.ofbiz.pos.adaptor.KeyboardAdaptor; |
| import org.ofbiz.pos.component.InputWithPassword; |
| import org.ofbiz.pos.component.Journal; |
| import org.ofbiz.pos.component.Operator; |
| import org.ofbiz.pos.component.Output; |
| import org.ofbiz.pos.component.PosButton; |
| import org.ofbiz.pos.component.PromoStatusBar; |
| import org.ofbiz.pos.device.DeviceLoader; |
| |
| @SuppressWarnings("serial") |
| public class PosScreen extends XPage implements Runnable, DialogCallback, FocusListener { |
| |
| |
| public static final String module = PosScreen.class.getName(); |
| public static final Frame appFrame = XProjectManager.getCurrentProject().getAppFrame(); |
| public static final Window appWin = XProjectManager.getCurrentProject().getAppWindow(); |
| public static final String BUTTON_ACTION_METHOD = "buttonPressed"; |
| public static final long MAX_INACTIVITY = Long.valueOf(UtilProperties.getPropertyValue(PosTransaction.resource, "MaxInactivity", "1800000")); |
| public static PosScreen currentScreen; |
| |
| protected XProject currentProject = XProjectManager.getCurrentProject(); |
| protected static boolean monitorRunning = false; |
| protected static boolean firstInit = false; |
| protected static long lastActivity = 0; |
| protected static Thread activityMonitor = null; |
| |
| protected ClassLoader classLoader = null; |
| protected XuiSession session = null; |
| protected Output output = null; |
| protected InputWithPassword input = null; |
| protected Journal journal = null; |
| protected Operator operator = null; |
| protected PosButton buttons = null; |
| protected String scrLocation = null; |
| protected boolean isLocked = false; |
| protected boolean inDialog = false; |
| protected PromoStatusBar promoStatusBar = null; |
| |
| private Locale defaultLocale = Locale.getDefault(); |
| |
| public PosScreen() { |
| super(); |
| this.classLoader = Thread.currentThread().getContextClassLoader(); |
| this.addFocusListener(this); |
| } |
| |
| @Override |
| public void pageCreated() { |
| super.pageCreated(); |
| |
| // initial settings |
| this.setEnabled(false); |
| this.setVisible(false); |
| |
| // setup the shared components |
| this.session = XuiContainer.getSession(); |
| this.output = new Output(this); |
| this.input = new InputWithPassword(this); |
| this.journal = new Journal(this); |
| this.operator = new Operator(this); |
| this.promoStatusBar = new PromoStatusBar(this); |
| this.setLastActivity(System.currentTimeMillis()); |
| |
| if (!firstInit) { |
| firstInit = true; |
| |
| // pre-load a few screens |
| |
| currentProject.getPageManager().loadPage(this.getScreenLocation() + "/paypanel"); |
| currentProject.getPageManager().loadPage(this.getScreenLocation() + "/mgrpanel"); |
| currentProject.getPageManager().loadPage(this.getScreenLocation() + "/promopanel"); |
| |
| // start the shared monitor thread |
| if (activityMonitor == null) { |
| monitorRunning = true; |
| activityMonitor = new Thread(this); |
| activityMonitor.setDaemon(false); |
| activityMonitor.start(); |
| } |
| |
| // configure the window listener |
| KeyboardAdaptor.attachComponents(appWin, false); |
| appFrame.addFocusListener(this); |
| appWin.addFocusListener(this); |
| |
| // close the splash screen |
| SplashLoader.close(); |
| } |
| |
| // buttons are different per screen |
| this.buttons = new PosButton(this); |
| |
| // make sure all components have the keyboard set |
| KeyboardAdaptor.attachComponents(this); |
| } |
| |
| @Override |
| public void pageActivated() { |
| super.pageActivated(); |
| |
| this.setLastActivity(System.currentTimeMillis()); |
| |
| // The input receives keyboard events even when it's page is deactivated, so |
| // we'll clear it early to prevent the characters from displaying momentarily |
| input.clearInput(); |
| |
| if (session.getUserLogin() == null) { |
| this.setLock(true); |
| } else { |
| this.setLock(isLocked); |
| } |
| |
| currentScreen = this; |
| this.refresh(); |
| } |
| |
| @Override |
| public void pageDeactivated() { |
| super.pageDeactivated(); |
| |
| if (Debug.verboseOn()) { |
| this.logInfo(); |
| } |
| } |
| |
| public void logInfo() { |
| Debug.logInfo("App Frame :", module); |
| Debug.logInfo("name - " + appFrame.getName(), module); |
| Debug.logInfo("title - " + appFrame.getTitle(), module); |
| Debug.logInfo("active - " + appFrame.isActive(), module); |
| Debug.logInfo("enabled - " + appFrame.isEnabled(), module); |
| Debug.logInfo("visible - " + appFrame.isVisible(), module); |
| Debug.logInfo("showing - " + appFrame.isShowing(), module); |
| Debug.logInfo("opaque - " + appFrame.isOpaque(), module); |
| Debug.logInfo("focusable - " + appFrame.isFocusable(), module); |
| Debug.logInfo("focused - " + appFrame.isFocused(), module); |
| Debug.logInfo("hasFocus - " + appFrame.hasFocus(), module); |
| |
| Debug.logInfo("", module); |
| Debug.logInfo("App Window :", module); |
| Debug.logInfo("name - " + appWin.getName(), module); |
| Debug.logInfo("active - " + appWin.isActive(), module); |
| Debug.logInfo("enabled - " + appWin.isEnabled(), module); |
| Debug.logInfo("visible - " + appWin.isVisible(), module); |
| Debug.logInfo("showing - " + appWin.isShowing(), module); |
| Debug.logInfo("opaque - " + appWin.isOpaque(), module); |
| Debug.logInfo("focusable - " + appWin.isFocusable(), module); |
| Debug.logInfo("focused - " + appWin.isFocused(), module); |
| Debug.logInfo("hasFocus - " + appWin.hasFocus(), module); |
| |
| Debug.logInfo("", module); |
| |
| Debug.logInfo("POS Screen :", module); |
| Debug.logInfo("name - " + this.getName(), module); |
| Debug.logInfo("enabled - " + this.isEnabled(), module); |
| Debug.logInfo("visible - " + this.isVisible(), module); |
| Debug.logInfo("showing - " + this.isShowing(), module); |
| Debug.logInfo("opaque - " + this.isOpaque(), module); |
| Debug.logInfo("focusable - " + this.isFocusable(), module); |
| Debug.logInfo("focused - " + this.hasFocus(), module); |
| } |
| |
| public void refresh() { |
| this.refresh(true); |
| } |
| |
| public void refresh(boolean updateOutput) { |
| PosTransaction trans = PosTransaction.getCurrentTx(this.getSession()); |
| if (trans == null) { |
| updateOutput = false; |
| } |
| |
| appFrame.requestFocus(); |
| this.lockScreenButton(this); |
| //this.requestFocus(); |
| |
| if (!isLocked) { |
| this.setEnabled(true); |
| this.setVisible(true); |
| journal.refresh(this); |
| input.clearInput(); |
| operator.refresh(); |
| if (updateOutput) { |
| if (input.isFunctionSet("PAID")) { |
| output.print(UtilProperties.getMessage(PosTransaction.resource,"PosChange",defaultLocale) |
| + UtilFormatOut.formatPrice(trans.getTotalDue().negate())); |
| } else if (input.isFunctionSet("TOTAL")) { |
| if (trans.getTotalDue().compareTo(BigDecimal.ZERO) > 0) { |
| output.print(UtilProperties.getMessage(PosTransaction.resource,"PosTotalD",defaultLocale) + " " + UtilFormatOut.formatPrice(trans.getTotalDue())); |
| } else { |
| output.print(UtilProperties.getMessage(PosTransaction.resource,"PosPayFin",defaultLocale)); |
| } |
| } else { |
| if (PosTransaction.getCurrentTx(session).isOpen()) { |
| output.print(UtilProperties.getMessage(PosTransaction.resource,"PosIsOpen",defaultLocale)); |
| } else { |
| output.print(UtilProperties.getMessage(PosTransaction.resource,"PosIsClosed",defaultLocale)); |
| } |
| } |
| } else { |
| promoStatusBar.clear(); |
| } |
| //journal.focus(); |
| } else { |
| output.print(UtilProperties.getMessage(PosTransaction.resource,"PosULogin",defaultLocale)); |
| //input.focus(); |
| } |
| |
| this.repaint(); |
| //this.logInfo(); |
| } |
| |
| public boolean isLocked() { |
| return isLocked; |
| } |
| |
| public void setLock(boolean lock) { |
| this.buttons.setLock(lock); |
| this.input.setLock(lock); |
| this.output.setLock(lock); |
| this.journal.setLock(lock); |
| this.operator.setLock(lock); |
| this.isLocked = lock; |
| if (lock) { |
| this.input.setFunction("LOGIN"); |
| } |
| DeviceLoader.enable(!lock); |
| } |
| |
| public XuiSession getSession() { |
| return this.session; |
| } |
| |
| public InputWithPassword getInput() { |
| return this.input; |
| } |
| |
| public Output getOutput() { |
| return this.output; |
| } |
| |
| public Journal getJournal() { |
| return this.journal; |
| } |
| |
| public PosButton getButtons() { |
| return this.buttons; |
| } |
| |
| public PromoStatusBar getPromoStatusBar() { |
| return this.promoStatusBar; |
| } |
| |
| public void setLastActivity(long l) { |
| lastActivity = l; |
| } |
| |
| public ClassLoader getClassLoader() { |
| return classLoader; |
| } |
| |
| // generic button XUI event calls into PosButton to lookup the external reference |
| public synchronized void buttonPressed() { |
| this.setLastActivity(System.currentTimeMillis()); |
| buttons.buttonPressed(this, (AWTEvent)this.getCurrentEvent()); |
| journal.focus(); |
| } |
| |
| // generic page display methods - extends those in XPage |
| @Override |
| public PosScreen showPage(String pageName) { |
| return this.showPage(pageName, true); |
| } |
| |
| public PosScreen showPage(String pageName, boolean refresh) { |
| if (pageName.startsWith("/")) { |
| pageName = pageName.substring(1); |
| } |
| XPage newPage = (XPage)currentProject.getPageManager().showPage(this.getScreenLocation() + "/" + pageName); |
| if (newPage instanceof PosScreen) { |
| if (refresh) ((PosScreen) newPage).refresh(); |
| return (PosScreen) newPage; |
| } |
| return null; |
| } |
| |
| public void lockScreenButton(PosScreen pos) { |
| if ((this.getScreenLocation() + "/pospanel").equals(pos.getName())) { |
| pos.getButtons().setLock("menuMain", true); |
| } else if ((this.getScreenLocation() + "/mgrpanel").equals(pos.getName())) { |
| pos.getButtons().setLock("menuMgr", true); |
| } else if ((this.getScreenLocation() + "/paypanel").equals(pos.getName())) { |
| pos.getButtons().setLock("menuPay", true); |
| } else if ((this.getScreenLocation() + "/promopanel").equals(pos.getName())) { |
| pos.getButtons().setLock("menuPromo", true); |
| } |
| } |
| |
| public PosDialog showDialog(String pageName) { |
| return showDialog(pageName, this, null); |
| } |
| |
| public PosDialog showDialog(String pageName, String text) { |
| return showDialog(pageName, this, text); |
| } |
| |
| public PosDialog showDialog(String pageName, DialogCallback cb) { |
| return showDialog(pageName, cb, null); |
| } |
| |
| public PosDialog showDialog(String pageName, DialogCallback cb, String text) { |
| if (pageName.startsWith("/")) { |
| pageName = pageName.substring(1); |
| } |
| XPage dialogPage = (XPage)currentProject.getPageManager().loadPage(this.getScreenLocation() + "/" + pageName); |
| PosDialog dialog = PosDialog.getInstance(dialogPage, true, 0); |
| dialog.showDialog(this, cb, text); |
| return dialog; |
| } |
| |
| // PosDialog Callback method |
| public void receiveDialogCb(PosDialog dialog) { |
| Debug.logInfo("Dialog closed; refreshing screen", module); |
| this.refresh(); |
| } |
| |
| // run method for auto-locking POS on inactivity |
| public void run() { |
| while (monitorRunning) { |
| if (!isLocked && (System.currentTimeMillis() - lastActivity) > MAX_INACTIVITY) { |
| Debug.logInfo("POS terminal auto-lock activated", module); |
| PosScreen.currentScreen.showPage("pospanel").setLock(true); |
| } |
| try { |
| Thread.sleep(5000); |
| } catch (InterruptedException e) { |
| Debug.logError(e, module); |
| } |
| } |
| } |
| |
| public void focusGained(FocusEvent event) { |
| if (Debug.verboseOn()) { |
| String from = event != null && event.getOppositeComponent() != null ? event.getOppositeComponent().getName() : "??"; |
| Debug.logInfo(event.getSource() + " focus gained from " + from, module); |
| } |
| } |
| |
| public void focusLost(FocusEvent event) { |
| if (Debug.verboseOn()) { |
| String to = event != null && event.getOppositeComponent() != null ? event.getOppositeComponent().getName() : "??"; |
| Debug.logInfo(event.getSource() + " focus lost to " + to, module); |
| } |
| } |
| |
| public String getScreenLocation() { |
| if (this.scrLocation == null) { |
| synchronized(this) { |
| if (this.scrLocation == null) { |
| String xuiProps = this.getSession().getContainer().getXuiPropertiesName(); |
| String startClass = UtilProperties.getPropertyValue(xuiProps, "StartClass", "default/pospanel"); |
| this.scrLocation = startClass.substring(0, startClass.lastIndexOf("/")); |
| } |
| } |
| } |
| return this.scrLocation; |
| } |
| |
| public void setWaitCursor() { |
| setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR)); |
| } |
| public void setNormalCursor() { |
| setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR)); |
| } |
| } |