From 3c95eafdf4cf86c4368b47189be26520c7b53c26 Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Tue, 16 Dec 2008 23:11:36 +0000 Subject: [PATCH] [ 2435685 ] FR: Pluggable desktop presentation --- .../org/adempiere/webui/AdempiereWebUI.java | 43 +- .../src/org/adempiere/webui/Desktop.java | 1027 ----------------- .../org/adempiere/webui/IDashboardPanel.java | 7 - .../src/org/adempiere/webui/IDesktop.java | 125 -- .../src/org/adempiere/webui/IWebClient.java | 2 + .../adempiere/webui/apps/ProcessDialog.java | 4 +- .../adempiere/webui/component/Accordion.java | 159 +++ .../webui/{ => dashboard}/DPActivities.java | 5 +- .../webui/{ => dashboard}/DPCalendar.java | 3 +- .../webui/{ => dashboard}/DPFavourites.java | 3 +- .../webui/{ => dashboard}/DPPerformance.java | 3 +- .../webui/{ => dashboard}/DPViews.java | 3 +- .../webui/{ => dashboard}/DashboardPanel.java | 5 +- .../webui/dashboard/DashboardRunnable.java | 83 ++ .../webui/dashboard/IDashboardPanel.java | 29 + .../webui/desktop/AbstractDesktop.java | 393 +++++++ .../webui/desktop/DefaultDesktop.java | 385 ++++++ .../org/adempiere/webui/desktop/IDesktop.java | 177 +++ .../webui/desktop/LeftBar2Desktop.java | 425 +++++++ .../webui/desktop/LeftBarDesktop.java | 417 +++++++ .../webui/desktop/TabbedDesktop.java | 285 +++++ .../webui/session/SessionManager.java | 2 +- .../org/adempiere/webui/window/ADWindow.java | 4 +- zkwebui/zul/activities.zul | 2 +- zkwebui/zul/calendar.zul | 2 +- zkwebui/zul/favourites.zul | 2 +- zkwebui/zul/performance.zul | 2 +- zkwebui/zul/views.zul | 2 +- 28 files changed, 2415 insertions(+), 1184 deletions(-) delete mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/Desktop.java delete mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/IDashboardPanel.java delete mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/IDesktop.java create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/component/Accordion.java rename zkwebui/WEB-INF/src/org/adempiere/webui/{ => dashboard}/DPActivities.java (95%) rename zkwebui/WEB-INF/src/org/adempiere/webui/{ => dashboard}/DPCalendar.java (90%) rename zkwebui/WEB-INF/src/org/adempiere/webui/{ => dashboard}/DPFavourites.java (96%) rename zkwebui/WEB-INF/src/org/adempiere/webui/{ => dashboard}/DPPerformance.java (92%) rename zkwebui/WEB-INF/src/org/adempiere/webui/{ => dashboard}/DPViews.java (96%) rename zkwebui/WEB-INF/src/org/adempiere/webui/{ => dashboard}/DashboardPanel.java (88%) create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/IDashboardPanel.java create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/desktop/AbstractDesktop.java create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/desktop/IDesktop.java create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/desktop/LeftBar2Desktop.java create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/desktop/LeftBarDesktop.java create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/desktop/TabbedDesktop.java diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java b/zkwebui/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java index b35ddc24db..7aaaa7a6f6 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java @@ -21,8 +21,12 @@ import java.util.Properties; import javax.servlet.http.HttpSession; +import org.adempiere.webui.desktop.DefaultDesktop; +import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.session.SessionManager; import org.compiere.model.MSession; +import org.compiere.model.MSysConfig; +import org.compiere.util.CLogger; import org.compiere.util.Env; import org.compiere.util.Language; import org.zkoss.zk.ui.Executions; @@ -43,6 +47,8 @@ import org.zkoss.zul.Window; * @author Ashley G Ramdass * @date Feb 25, 2007 * @version $Revision: 0.10 $ + * + * @author hengsin */ public class AdempiereWebUI extends Window implements EventListener, IWebClient { @@ -50,15 +56,17 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient public static final String APP_NAME = "Adempiere ZK webUI"; - public static final String UID = "0.2"; + public static final String UID = "1.0"; private WLogin loginDesktop; - private Desktop appDesktop; + private IDesktop appDesktop; private ClientInfo clientInfo; private String langSession; + + private static final CLogger logger = CLogger.getCLogger(AdempiereWebUI.class); public AdempiereWebUI() { @@ -128,12 +136,12 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient Env.setContext(ctx, "#ShowAdvanced", true); IDesktop d = (IDesktop) currSess.getAttribute("application.desktop"); - if (d != null && d instanceof Desktop) + if (d != null && d instanceof IDesktop) { ExecutionCarryOver eco = (ExecutionCarryOver) currSess.getAttribute("execution.carryover"); if (eco != null) { //try restore - appDesktop = (Desktop) d; + appDesktop = (IDesktop) d; ExecutionCarryOver current = new ExecutionCarryOver(this.getPage().getDesktop()); ExecutionCtrl ctrl = ExecutionsCtrl.getCurrentCtrl(); @@ -162,7 +170,7 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient if (appDesktop == null) { //create new desktop - appDesktop = new Desktop(); + createDesktop(); appDesktop.setClientInfo(clientInfo); appDesktop.createPart(this.getPage()); currSess.setAttribute("application.desktop", appDesktop); @@ -171,7 +179,28 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient } } - /* (non-Javadoc) + private void createDesktop() + { + appDesktop = null; + String className = MSysConfig.getValue(IDesktop.CLASS_NAME_KEY); + if ( className != null && className.trim().length() > 0) + { + try + { + Class clazz = this.getClass().getClassLoader().loadClass(className); + appDesktop = (IDesktop) clazz.newInstance(); + } + catch (Throwable t) + { + logger.warning("Failed to instantiate desktop. Class=" + className); + } + } + //fallback to default + if (appDesktop == null) + appDesktop = new DefaultDesktop(); + } + + /* (non-Javadoc) * @see org.adempiere.webui.IWebClient#logout() */ public void logout() @@ -190,7 +219,7 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient Executions.sendRedirect("index.zul"); } - public Desktop getAppDeskop() + public IDesktop getAppDeskop() { return appDesktop; } diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/Desktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/Desktop.java deleted file mode 100644 index 36e0a56325..0000000000 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/Desktop.java +++ /dev/null @@ -1,1027 +0,0 @@ -/****************************************************************************** - * Product: Posterita Ajax UI * - * Copyright (C) 2007 Posterita Ltd. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it * - * under the terms version 2 of the GNU General Public License as published * - * by the Free Software Foundation. This program is distributed in the hope * - * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * - * See the GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along * - * with this program; if not, write to the Free Software Foundation, Inc., * - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * - * For the text or an alternative of this public license, you may reach us * - * Posterita Ltd., 3, Draper Avenue, Quatre Bornes, Mauritius * - * or via info@posterita.org or http://www.posterita.org/ * - *****************************************************************************/ - -package org.adempiere.webui; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Serializable; -import java.net.URL; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; - -import org.adempiere.apps.graph.BarGraphColumn; -import org.adempiere.webui.apps.AEnv; -import org.adempiere.webui.apps.ProcessDialog; -import org.adempiere.webui.apps.graph.WBarGraph; -import org.adempiere.webui.apps.wf.WFPanel; -import org.adempiere.webui.component.DesktopTabpanel; -import org.adempiere.webui.component.Tabbox; -import org.adempiere.webui.component.Tabpanel; -import org.adempiere.webui.component.ToolBarButton; -import org.adempiere.webui.component.Window; -import org.adempiere.webui.event.MenuListener; -import org.adempiere.webui.exception.ApplicationException; -import org.adempiere.webui.panel.ADForm; -import org.adempiere.webui.panel.HeaderPanel; -import org.adempiere.webui.panel.SidePanel; -import org.adempiere.webui.part.AbstractUIPart; -import org.adempiere.webui.part.WindowContainer; -import org.adempiere.webui.window.ADWindow; -import org.adempiere.webui.window.WTask; -import org.compiere.model.MAchievement; -import org.compiere.model.MGoal; -import org.compiere.model.MMeasureCalc; -import org.compiere.model.MMenu; -import org.compiere.model.MProjectType; -import org.compiere.model.MQuery; -import org.compiere.model.MRequestType; -import org.compiere.model.MRole; -import org.compiere.model.MTask; -import org.compiere.model.X_AD_Menu; -import org.compiere.model.X_PA_DashboardContent; -import org.compiere.util.CLogger; -import org.compiere.util.DB; -import org.compiere.util.Env; -import org.compiere.util.Msg; -import org.compiere.util.WebDoc; -import org.zkoss.util.media.AMedia; -import org.zkoss.zhtml.Button; -import org.zkoss.zk.ui.Component; -import org.zkoss.zk.ui.Executions; -import org.zkoss.zk.ui.Page; -import org.zkoss.zk.ui.event.Event; -import org.zkoss.zk.ui.event.EventListener; -import org.zkoss.zk.ui.event.Events; -import org.zkoss.zkex.zul.Borderlayout; -import org.zkoss.zkex.zul.Center; -import org.zkoss.zkex.zul.North; -import org.zkoss.zkex.zul.West; -import org.zkoss.zkmax.zul.Portalchildren; -import org.zkoss.zkmax.zul.Portallayout; -import org.zkoss.zul.Html; -import org.zkoss.zul.Iframe; -import org.zkoss.zul.Panel; -import org.zkoss.zul.Panelchildren; -import org.zkoss.zul.Tab; -import org.zkoss.zul.Tabpanels; - -/** - * - * @author Ashley G Ramdass - * @author Low Heng Sin - * @date Mar 2, 2007 - * @version $Revision: 0.10 $ - */ -public class Desktop extends AbstractUIPart implements MenuListener, Serializable, IDesktop, EventListener -{ - - public static final String WINDOWNO_ATTRIBUTE = "desktop.windowno"; - - private static final long serialVersionUID = 9056511175189603883L; - - private static final CLogger logger = CLogger.getCLogger(Desktop.class); - - private transient ClientInfo clientInfo; - - private List windows; - - private Center windowArea; - - private Borderlayout layout; - - private WindowContainer windowContainer; - - private List dashboardPanels; - - private MGoal[] m_goals = null; - - private List queryZoom = null; - - private Thread updateInfoThread; - - private UpdateInfoRunnable updateInfoRunnable; - - private static final String key = "queryZoom"; - - public Desktop() - { - windows = new ArrayList(); - dashboardPanels = new ArrayList(); - m_goals = MGoal.getUserGoals(Env.getCtx(), Env.getAD_User_ID(Env.getCtx())); - queryZoom = new ArrayList(); - } - - protected Component doCreatePart(Component parent) - { - SidePanel pnlSide = new SidePanel(); - HeaderPanel pnlHead = new HeaderPanel(); - - pnlSide.getMenuPanel().addMenuListener(this); - - layout = new Borderlayout(); - if (parent != null) - { - layout.setParent(parent); - layout.setWidth("100%"); - layout.setHeight("100%"); - layout.setStyle("position: absolute"); - } - else - layout.setPage(page); - - North n = new North(); - layout.appendChild(n); - n.setCollapsible(false); - pnlHead.setParent(n); - - West w = new West(); - layout.appendChild(w); - w.setWidth("300px"); - w.setCollapsible(true); - w.setSplittable(true); - w.setTitle("Menu"); - w.setTooltiptext("Application Menu"); - w.setFlex(true); -// w.setAutoscroll(true); - pnlSide.setParent(w); - - windowArea = new Center(); - windowArea.setParent(layout); - windowArea.setFlex(true); -// windowArea.setAutoscroll(true); - windowContainer = new WindowContainer(); - windowContainer.createPart(windowArea); - - createHomeTab(); - - return layout; - } - - private void createHomeTab() - { - Tabpanel homeTab = new Tabpanel(); - windowContainer.addWindow(homeTab, Msg.getMsg(Env.getCtx(), "Home").replaceAll("&", ""), false); - - Portallayout layout = new Portallayout(); - layout.setWidth("100%"); - homeTab.appendChild(layout); - - // Dashboard content - Portalchildren portalchildren = null; - int currentColumnNo = 0; - - String sql = "SELECT COUNT(DISTINCT COLUMNNO) " - + "FROM PA_DASHBOARDCONTENT " - + "WHERE (AD_CLIENT_ID=0 OR AD_CLIENT_ID=?) AND ISACTIVE='Y'"; - - int noOfCols = DB.getSQLValue(null, sql, - Env.getAD_Client_ID(Env.getCtx())); - - int width = noOfCols <= 0 ? 100 : 100/noOfCols; - - sql = "SELECT x.*, m.AD_MENU_ID " - + "FROM PA_DASHBOARDCONTENT x " - + "LEFT OUTER JOIN AD_MENU m ON x.AD_WINDOW_ID=m.AD_WINDOW_ID " - + "WHERE (x.AD_CLIENT_ID=0 OR x.AD_CLIENT_ID=?) AND x.ISACTIVE='Y' " - + "ORDER BY x.COLUMNNO, x.AD_CLIENT_ID, x.LINE "; - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement(sql, null); - pstmt.setInt(1, Env.getAD_Client_ID(Env.getCtx())); - rs = pstmt.executeQuery(); - - while (rs.next()) - { - int columnNo = rs.getInt(X_PA_DashboardContent.COLUMNNAME_ColumnNo); - if(portalchildren == null || currentColumnNo != columnNo) - { - portalchildren = new Portalchildren(); - layout.appendChild(portalchildren); - portalchildren.setWidth(width + "%"); - portalchildren.setStyle("padding: 5px"); - - currentColumnNo = columnNo; - } - - Panel panel = new Panel(); - panel.setStyle("margin-bottom:10px"); - panel.setTitle(rs.getString(X_PA_DashboardContent.COLUMNNAME_Name)); - - String description = rs.getString(X_PA_DashboardContent.COLUMNNAME_Description); - if(description != null) - panel.setTooltiptext(description); - - String collapsible = rs.getString(X_PA_DashboardContent.COLUMNNAME_IsCollapsible); - panel.setCollapsible(collapsible.equals("Y")); - - panel.setBorder("normal"); - portalchildren.appendChild(panel); - Panelchildren content = new Panelchildren(); - panel.appendChild(content); - - boolean panelEmpty = true; - - // HTML content - String htmlContent = rs.getString(X_PA_DashboardContent.COLUMNNAME_HTML); - if(htmlContent != null) - { - StringBuffer result = new StringBuffer(""); - - URL url = getClass().getClassLoader(). - getResource("org/compiere/images/PAPanel.css"); - InputStreamReader ins; - try { - ins = new InputStreamReader(url.openStream()); - BufferedReader bufferedReader = new BufferedReader( ins ); - String cssLine; - while ((cssLine = bufferedReader.readLine()) != null) - result.append(cssLine + "\n"); - } catch (IOException e1) { - logger.log(Level.SEVERE, e1.getLocalizedMessage(), e1); - } - - result.append("
\n"); - -// if(description != null) -// result.append("

" + description + "

\n"); - result.append(stripHtml(htmlContent, false) + "
\n"); - result.append("
\n\n\n"); - - Html html = new Html(); - html.setContent(result.toString()); - content.appendChild(html); - panelEmpty = false; - } - - // Window - int AD_Window_ID = rs.getInt(X_PA_DashboardContent.COLUMNNAME_AD_Window_ID); - if(AD_Window_ID > 0) - { - int AD_Menu_ID = rs.getInt(X_AD_Menu.COLUMNNAME_AD_Menu_ID); - ToolBarButton btn = new ToolBarButton(String.valueOf(AD_Menu_ID)); - MMenu menu = new MMenu(Env.getCtx(), AD_Menu_ID, null); - btn.setLabel(menu.getName()); - btn.addEventListener(Events.ON_CLICK, this); - content.appendChild(btn); - panelEmpty = false; - } - - // Goal - int PA_Goal_ID = rs.getInt(X_PA_DashboardContent.COLUMNNAME_PA_Goal_ID); - if(PA_Goal_ID > 0) - { - StringBuffer result = new StringBuffer(""); - - URL url = getClass().getClassLoader(). - getResource("org/compiere/images/PAPanel.css"); - InputStreamReader ins; - try { - ins = new InputStreamReader(url.openStream()); - BufferedReader bufferedReader = new BufferedReader( ins ); - String cssLine; - while ((cssLine = bufferedReader.readLine()) != null) - result.append(cssLine + "\n"); - } catch (IOException e1) { - logger.log(Level.SEVERE, e1.getLocalizedMessage(), e1); - } - - result.append("
\n"); - result.append(goalsDetail(PA_Goal_ID, content)); - result.append("
\n\n\n"); - - Html html = new Html(); - html.setContent(result.toString()); - content.appendChild(html); - panelEmpty = false; - } - - // ZUL file url - String url = rs.getString(X_PA_DashboardContent.COLUMNNAME_ZulFilePath); - if(url != null) - { - try { - Component component = Executions.createComponents(url, content, null); - if(component != null) - { - if (component instanceof DashboardPanel) - { - DashboardPanel dashboardPanel = (DashboardPanel) component; - if (!dashboardPanel.getChildren().isEmpty()) { - content.appendChild(dashboardPanel); - dashboardPanels.add(dashboardPanel); - panelEmpty = false; - } - } - else - { - content.appendChild(component); - panelEmpty = false; - } - } - } catch (Exception e) { - logger.log(Level.WARNING, "Failed to create components. zul="+url, e); - } - } - - if (panelEmpty) - panel.detach(); - } - } catch(Exception e) { - logger.log(Level.WARNING, "Failed to create dashboard content", e); - } finally { - DB.close(rs, pstmt); - } - // - - //register as 0 - registerWindow(homeTab); - - if (!layout.getDesktop().isServerPushEnabled()) - layout.getDesktop().enableServerPush(true); - - updateInfo(); - - updateInfoRunnable = new UpdateInfoRunnable(layout.getDesktop()); - updateInfoThread = new Thread(updateInfoRunnable, "UpdateInfo"); - updateInfoThread.setDaemon(true); - updateInfoThread.start(); - } - - private String goalsDetail(int AD_Table_ID, Panelchildren panel) - { - String output = ""; - if (m_goals == null) - return output; - - for (int i = 0; i < m_goals.length; i++) - { - MMeasureCalc mc = MMeasureCalc.get(Env.getCtx(), m_goals[i].getMeasure().getPA_MeasureCalc_ID()); - - if (AD_Table_ID == m_goals[i].getPA_Goal_ID()) - { - output += "\n\n"; - output += "\n"; - output += "\n"; - - WBarGraph barPanel = new WBarGraph(m_goals[i]); - BarGraphColumn[] bList = barPanel.getBarGraphColumnList(); - MQuery query = null; - output += "\n"; - - for (int k = 0; k < bList.length; k++) - { - BarGraphColumn bgc = bList[k]; - if (k > 0) - output += ""; - if (bgc.getAchievement() != null) // Single Achievement - { - MAchievement a = bgc.getAchievement(); - query = MQuery.getEqualQuery("PA_Measure_ID", a.getPA_Measure_ID()); - } - else if (bgc.getGoal() != null) // Multiple Achievements - { - MGoal goal = bgc.getGoal(); - query = MQuery.getEqualQuery("PA_Measure_ID", goal.getPA_Measure_ID()); - } - else if (bgc.getMeasureCalc() != null) // Document - { - mc = bgc.getMeasureCalc(); - query = mc.getQuery(m_goals[i].getRestrictions(false), bgc.getMeasureDisplay(), - bgc.getDate(), MRole.getDefault()); // logged in role - } - else if (bgc.getProjectType() != null) // Document - { - MProjectType pt = bgc.getProjectType(); - query = pt.getQuery(m_goals[i].getRestrictions(false), bgc.getMeasureDisplay(), - bgc.getDate(), bgc.getID(), MRole.getDefault()); // logged in role - } - else if (bgc.getRequestType() != null) // Document - { - MRequestType rt = bgc.getRequestType(); - query = rt.getQuery(m_goals[i].getRestrictions(false), bgc.getMeasureDisplay(), - bgc.getDate(), bgc.getID(), MRole.getDefault()); // logged in role - } - output += ""; - } - output += "" - + "" - + "
" - + m_goals[i].getName() + "
Target" - + m_goals[i].getMeasureTarget() + "
Actual" - + m_goals[i].getMeasureActual() + "
" - + m_goals[i].getXAxisText() + "
" + bgc.getLabel() - + ""; - if (query != null) { - Button btn = new Button(); - btn.setId(String.valueOf(key + queryZoom.size())); - btn.addEventListener(Events.ON_CLICK, this); - btn.setVisible(false); - panel.appendChild(btn); - - output += "" - + bgc.getValue() - + "
\n"; - - queryZoom.add(query); - } else { - logger.info("Nothing to zoom to - " + bgc); - output += bgc.getValue(); - } - output += "
" - + m_goals[i].getDescription() - + "
" - + stripHtml(m_goals[i].getColorSchema() - .getDescription(), true) + "
\n"; - bList = null; - barPanel = null; - } - } - - return output; - } - - private String stripHtml(String htmlString, boolean all) { - htmlString = htmlString - .replace("", "") - .replace("", "") - .replace("", "") - .replace("", "") - .replace("", "") - .replace("", ""); - - if (all) - htmlString = htmlString - .replace(">", ">") - .replace("<", "<"); - return htmlString; - } - - private class UpdateInfoRunnable implements Runnable { - private org.zkoss.zk.ui.Desktop desktop; - private boolean stop = false; - UpdateInfoRunnable(org.zkoss.zk.ui.Desktop desktop) { - this.desktop = desktop; - } - public void run() - { - while(!stop) { - try { - Thread.sleep(60000); // Update every one minutes - } catch (InterruptedException e1) { - if (stop) break; - } - - try { - // get full control of desktop - Executions.activate(desktop); - try { - updateInfo(); - } catch (Error ex) { - logger.log(Level.WARNING, "UpdateInfo Thread error="+ex.getLocalizedMessage(), ex); - break; - } finally { - // release full control of desktop - Executions.deactivate(desktop); - } - } catch (Throwable e) { - logger.log(Level.WARNING, "UpdateInfo Thread error="+e.getLocalizedMessage(), e); - break; - } - } - } - } - - public void onEvent(Event event) - { - Component comp = event.getTarget(); - String eventName = event.getName(); - - if(eventName.equals(Events.ON_CLICK)) - { - if(comp instanceof ToolBarButton) - { - ToolBarButton btn = (ToolBarButton) comp; - - int menuId = 0; - try - { - menuId = Integer.valueOf(btn.getName()); - } - catch (Exception e) { - - } - - if(menuId > 0) onMenuSelected(menuId); - } - else if(comp instanceof Button) - { - String id = comp.getId(); - String key = "queryZoom"; - if(id.startsWith(key)) - { - String ss = id.substring(key.length()); - int index = Integer.parseInt(String.valueOf(ss)); - if ((index >= 0) && (index < queryZoom.size())) - AEnv.zoom(queryZoom.get(index)); - } - } - } - } - - private void updateInfo() - { - for(int i = 0; i < dashboardPanels.size(); i++) - dashboardPanels.get(i).updateInfo(); - - int noOfNotice = DPActivities.getNoticeCount(); - int noOfRequest = DPActivities.getRequestCount(); - int noOfWorkflow = DPActivities.getWorkflowCount(); - int total = noOfNotice + noOfRequest + noOfWorkflow; - - windowContainer.setTabTitle(0, "Home (" + total + ")", - "Notice : " + noOfNotice + ", Request : " + noOfRequest + ", Workflow Activities : " + noOfWorkflow); - } - - /** - * Event listener for menu item selection. - * Identifies the action associated with the selected - * menu item and acts accordingly. - * - * @param menuId Identifier for the selected menu item - * - * @throws ApplicationException If the selected menu action has yet - * to be implemented - */ - public void onMenuSelected(int menuId) - { - MMenu menu = new MMenu(Env.getCtx(), menuId, null); - if(menu == null) - { - return; - } - - if(menu.getAction().equals(MMenu.ACTION_Window)) - { - openWindow(menu.getAD_Window_ID()); - } - else if(menu.getAction().equals(MMenu.ACTION_Process) || - menu.getAction().equals(MMenu.ACTION_Report)) - { - openProcessDialog(menu.getAD_Process_ID(), menu.isSOTrx()); - } - else if(menu.getAction().equals(MMenu.ACTION_Form)) - { - openForm(menu.getAD_Form_ID()); - } - else if(menu.getAction().equals(MMenu.ACTION_WorkFlow)) - { - openWorkflow(menu.getAD_Workflow_ID()); - } - else if(menu.getAction().equals(MMenu.ACTION_Task)) - { - openTask(menu.getAD_Task_ID()); - } - else - { - throw new ApplicationException("Menu Action not yet implemented: " + menu.getAction()); - } - } - - /** - * - * @param taskId - */ - public void openTask(int taskId) { - MTask task = new MTask(Env.getCtx(), taskId, null); - new WTask(task.getName(), task); - } - - /** - * - * @param processId - * @param soTrx - * @return ProcessDialog - */ - public ProcessDialog openProcessDialog(int processId, boolean soTrx) { - ProcessDialog pd = new ProcessDialog (processId, soTrx); - if (pd.isValid()) { - DesktopTabpanel tabPanel = new DesktopTabpanel(); - pd.setParent(tabPanel); - String title = pd.getTitle(); - pd.setTitle(null); - windowContainer.addWindow(tabPanel, title, true); - } - return pd; - } - - /** - * - * @param formId - * @return ADWindow - */ - public ADForm openForm(int formId) { - ADForm form = ADForm.openForm(formId); - - DesktopTabpanel tabPanel = new DesktopTabpanel(); - form.setParent(tabPanel); - //do not show window title when open as tab - form.setTitle(null); - windowContainer.addWindow(tabPanel, form.getFormName(), true); - - return form; - } - - /** - * - * @param workflow_ID - */ - public void openWorkflow(int workflow_ID) { - WFPanel p = new WFPanel(); - p.load(workflow_ID); - - DesktopTabpanel tabPanel = new DesktopTabpanel(); - p.setParent(tabPanel); - windowContainer.addWindow(tabPanel, p.getWorkflow().getName(), true); - } - - /** - * - * @param windowId - * @return ADWindow - */ - public ADWindow openWindow(int windowId) { - ADWindow adWindow = new ADWindow(Env.getCtx(), windowId); - - DesktopTabpanel tabPanel = new DesktopTabpanel(); - if (adWindow.createPart(tabPanel) != null) { - windowContainer.addWindow(tabPanel, adWindow.getTitle(), true); - return adWindow; - } else { - //user cancel - return null; - } - } - - /** - * @param url - */ - public void showURL(String url, boolean closeable) - { - showURL(url, url, closeable); - } - - /** - * - * @param url - * @param title - * @param closeable - */ - public void showURL(String url, String title, boolean closeable) - { - Iframe iframe = new Iframe(url); - addWin(iframe, title, closeable); - } - - /** - * @param webDoc - * @param title - * @param closeable - */ - public void showURL(WebDoc webDoc, String title, boolean closeable) - { - Iframe iframe = new Iframe(); - - AMedia media = new AMedia(title, "html", "text/html", webDoc.toString().getBytes()); - iframe.setContent(media); - - addWin(iframe, title, closeable); - } - - /** - * - * @param fr - * @param title - * @param closeable - */ - private void addWin(Iframe fr, String title, boolean closeable) - { - fr.setWidth("100%"); - fr.setHeight("100%"); - fr.setStyle("padding: 0; margin: 0; border: none; position: absolute"); - Window window = new Window(); - window.setWidth("100%"); - window.setHeight("100%"); - window.setStyle("padding: 0; margin: 0; border: none"); - window.appendChild(fr); - window.setStyle("position: absolute"); - - Tabpanel tabPanel = new Tabpanel(); - window.setParent(tabPanel); - windowContainer.addWindow(tabPanel, title, closeable); - } - - /** - * @param AD_Window_ID - * @param query - */ - public void showZoomWindow(int AD_Window_ID, MQuery query) - { - ADWindow wnd = new ADWindow(Env.getCtx(), AD_Window_ID, query); - - DesktopTabpanel tabPanel = new DesktopTabpanel(); - wnd.createPart(tabPanel); - windowContainer.insertAfter(windowContainer.getSelectedTab(), tabPanel, wnd.getTitle(), true, true); - } - - /** - * @param win - */ - public void showWindow(Window win) - { - String pos = win.getPosition(); - this.showWindow(win, pos); - } - - /** - * @param win - * @param pos - */ - public void showWindow(Window win, String pos) - { - win.setPage(page); - Object objMode = win.getAttribute(Window.MODE_KEY); - - String mode = Window.MODE_MODAL; - - if (objMode != null) - { - mode = objMode.toString(); - } - - if (Window.MODE_MODAL.equals(mode)) - { - showModal(win); - } - else if (Window.MODE_POPUP.equals(mode)) - { - showPopup(win, pos); - } - else if (Window.MODE_OVERLAPPED.equals(mode)) - { - showOverlapped(win, pos); - } - else if (Window.MODE_EMBEDDED.equals(mode)) - { - showEmbedded(win); - } - else if (Window.MODE_HIGHLIGHTED.equals(mode)) - { - showHighlighted(win, pos); - } - } - - /** - * - * @param win - */ - private void showModal(Window win) - { - try - { - win.doModal(); - } - catch(InterruptedException e) - { - - } - - } - - /** - * - * @param win - * @param position - */ - private void showPopup(Window win, String position) - { - if (position == null) - win.setPosition("center"); - else - win.setPosition(position); - - win.doPopup(); - } - - /** - * - * @param win - * @param position - */ - private void showOverlapped(Window win, String position) - { - if (position == null) - win.setPosition("center"); - else - win.setPosition(position); - - win.doOverlapped(); - } - - /** - * - * @param win - * @param position - */ - private void showHighlighted(Window win, String position) - { - if (position == null) - win.setPosition("center"); - else - win.setPosition(position); - - win.doHighlighted(); - } - - /** - * - * @param window - */ - private void showEmbedded(Window window) - { - Tabpanel tabPanel = new Tabpanel(); - window.setParent(tabPanel); - String title = window.getTitle(); - window.setTitle(null); - if (Window.INSERT_NEXT.equals(window.getAttribute(Window.INSERT_POSITION_KEY))) - windowContainer.insertAfter(windowContainer.getSelectedTab(), tabPanel, title, true, true); - else - windowContainer.addWindow(tabPanel, title, true); - } - - /** - * @return clientInfo - */ - public ClientInfo getClientInfo() { - return clientInfo; - } - - /** - * - * @param clientInfo - */ - public void setClientInfo(ClientInfo clientInfo) { - this.clientInfo = clientInfo; - } - - /** - * @param win - */ - public int registerWindow(Object win) { - int retValue = windows.size(); - windows.add(win); - return retValue; - } - - /** - * @param WindowNo - */ - public void unregisterWindow(int WindowNo) { - if (WindowNo < windows.size()) - windows.set(WindowNo, null); - Env.clearWinContext(WindowNo); - } - - /** - * - * @param WindowNo - * @return Object - */ - public Object findWindow(int WindowNo) { - if (WindowNo < windows.size()) - return windows.get(WindowNo); - else - return null; - } - - /** - * Close active tab - * @return boolean - */ - public boolean closeActiveWindow() - { - if (windowContainer.getSelectedTab() != null) - { - Tabpanel panel = (Tabpanel) windowContainer.getSelectedTab().getLinkedPanel(); - Component component = panel.getFirstChild(); - Object att = component.getAttribute(WINDOWNO_ATTRIBUTE); - - if ( windowContainer.closeActiveWindow() ) - { - if (att != null && (att instanceof Integer)) - { - unregisterWindow((Integer) att); - } - return true; - } - else - { - return false; - } - } - return false; - } - - /** - * @return Component - */ - public Component getActiveWindow() - { - return windowContainer.getSelectedTab().getLinkedPanel().getFirstChild(); - } - - /** - * - * @param windowNo - * @return boolean - */ - public boolean closeWindow(int windowNo) - { - Tabbox tabbox = windowContainer.getComponent(); - Tabpanels panels = tabbox.getTabpanels(); - List childrens = panels.getChildren(); - for (Object child : childrens) - { - Tabpanel panel = (Tabpanel) child; - Component component = panel.getFirstChild(); - Object att = component.getAttribute(WINDOWNO_ATTRIBUTE); - if (att != null && (att instanceof Integer)) - { - if (windowNo == (Integer)att) - { - Tab tab = panel.getLinkedTab(); - panel.getLinkedTab().onClose(); - if (tab.getParent() == null) - { - unregisterWindow(windowNo); - return true; - } - else - { - return false; - } - } - } - } - return false; - } - - /** - * - * @param page - */ - public void setPage(Page page) { - if (this.page != page) { - layout.setPage(page); - this.page = page; - } - } - - /** - * Get the root component - * @return Component - */ - public Component getComponent() { - return layout; - } - - public void logout() { - if (updateInfoThread != null && updateInfoThread.isAlive()) { - updateInfoRunnable.stop = true; - updateInfoThread.interrupt(); - } - } -} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/IDashboardPanel.java b/zkwebui/WEB-INF/src/org/adempiere/webui/IDashboardPanel.java deleted file mode 100644 index bdfdf6864a..0000000000 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/IDashboardPanel.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.adempiere.webui; - -public interface IDashboardPanel { - - public void updateInfo(); - -} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/IDesktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/IDesktop.java deleted file mode 100644 index 4ae60ce996..0000000000 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/IDesktop.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.adempiere.webui; - -import org.adempiere.webui.apps.ProcessDialog; -import org.adempiere.webui.component.Window; -import org.adempiere.webui.panel.ADForm; -import org.adempiere.webui.window.ADWindow; -import org.compiere.model.MQuery; -import org.compiere.util.WebDoc; - -public interface IDesktop { - - /** - * - * @return ClientInfo - */ - public ClientInfo getClientInfo(); - - /** - * - * @param nodeId - */ - public void onMenuSelected(int nodeId); - - /** - * - * @param window - * @return windowNo - */ - public int registerWindow(Object window); - - /** - * - * @param WindowNo - * @return Object - */ - public Object findWindow(int WindowNo); - - /** - * close active window - * @return boolean - */ - public boolean closeActiveWindow(); - - /** - * - * @param windowNo - * @return boolean - */ - public boolean closeWindow(int windowNo); - - /** - * - * @param url - * @param closeable - */ - public void showURL(String url, boolean closeable); - - /** - * - * @param doc - * @param string - * @param closeable - */ - public void showURL(WebDoc doc, String string, boolean closeable); - - /** - * - * @param win - */ - public void showWindow(Window win); - - /** - * - * @param win - * @param position - */ - public void showWindow(Window win, String position); - - /** - * - * @param window_ID - * @param query - */ - public void showZoomWindow(int window_ID, MQuery query); - - /** - * - * @param windowNo - */ - public void unregisterWindow(int windowNo); - - /** - * - * @param processId - * @param soTrx - * @return ProcessDialog - */ - public ProcessDialog openProcessDialog(int processId, boolean soTrx); - - /** - * - * @param formId - * @return ADWindow - */ - public ADForm openForm(int formId); - - /** - * - * @param windowId - * @return ADWindow - */ - public ADWindow openWindow(int windowId); - - /** - * Open operating system task window - * @param task_ID - */ - public void openTask(int task_ID); - - /** - * - * @param workflow_ID - */ - public void openWorkflow(int workflow_ID); -} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/IWebClient.java b/zkwebui/WEB-INF/src/org/adempiere/webui/IWebClient.java index 2ae7f7499b..837cc4c461 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/IWebClient.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/IWebClient.java @@ -1,5 +1,7 @@ package org.adempiere.webui; +import org.adempiere.webui.desktop.IDesktop; + public interface IWebClient { public void loginCompleted(); diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java b/zkwebui/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java index 3c084f4e66..33920dfae0 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java @@ -11,11 +11,11 @@ import java.util.List; import java.util.Properties; import java.util.logging.Level; -import org.adempiere.webui.Desktop; import org.adempiere.webui.component.Button; import org.adempiere.webui.component.Panel; import org.adempiere.webui.component.VerticalBox; import org.adempiere.webui.component.Window; +import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.window.FDialog; import org.adempiere.webui.window.SimplePDFViewer; @@ -94,7 +94,7 @@ public class ProcessDialog extends Window implements EventListener//, ASyncProce log.info("Process=" + AD_Process_ID ); m_ctx = Env.getCtx();; m_WindowNo = SessionManager.getAppDesktop().registerWindow(this); - this.setAttribute(Desktop.WINDOWNO_ATTRIBUTE, m_WindowNo); + this.setAttribute(IDesktop.WINDOWNO_ATTRIBUTE, m_WindowNo); m_AD_Process_ID = AD_Process_ID; Env.setContext(Env.getCtx(), m_WindowNo, "IsSOTrx", isSOTrx ? "Y" : "N"); try diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/component/Accordion.java b/zkwebui/WEB-INF/src/org/adempiere/webui/component/Accordion.java new file mode 100644 index 0000000000..c1d8f825c9 --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/component/Accordion.java @@ -0,0 +1,159 @@ +/****************************************************************************** + * Copyright (C) 2008 Low Heng Sin * + * Copyright (C) 2008 Idalica Corporation * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.webui.component; + +import java.util.ArrayList; +import java.util.List; + +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zkex.zul.Borderlayout; +import org.zkoss.zkex.zul.Center; +import org.zkoss.zkex.zul.North; +import org.zkoss.zkex.zul.South; +import org.zkoss.zul.Div; +import org.zkoss.zul.Vbox; + +/** + * A custom accoridon implementation using borderlayout + * @author hengsin + * + */ +public class Accordion extends Borderlayout implements EventListener { + + private static final long serialVersionUID = 5898232602746332810L; + + private Vbox southBox; + private Vbox northBox; + + private List labelList = new ArrayList(); + private List buttonList = new ArrayList(); + private List componentList = new ArrayList(); + private int selectedIndex = -1; + + public Accordion() { + North north = new North(); + appendChild(north); + northBox = new Vbox(); + northBox.setWidth("100%"); + north.appendChild(northBox); + north.setSplittable(false); + north.setCollapsible(false); + + Center center = new Center(); + center.setFlex(true); + appendChild(new Center()); + + South south = new South(); + appendChild(south); + southBox = new Vbox(); + southBox.setWidth("100%"); + south.appendChild(southBox); + south.setSplittable(false); + south.setCollapsible(false); + } + + /** + * + * @param component + * @param label + */ + public void add(Component component, String label) { + ToolBarButton button = new ToolBarButton(); + button.setLabel(label); + button.addEventListener(Events.ON_CLICK, this); + button.setWidth("100%"); + + Div div = new Div(); + div.setClass("z-center-header"); + div.appendChild(button); + northBox.appendChild(div); + + labelList.add(label); + buttonList.add(button); + componentList.add(component); + } + + /** + * + * @param index + * @param label + */ + public void setLabel(int index, String label) { + labelList.set(index, label); + buttonList.get(index).setLabel(label); + if (selectedIndex == index) { + getCenter().setTitle(label); + } + } + + public void onEvent(Event event) throws Exception { + if (Events.ON_CLICK.equals(event.getName()) && event.getTarget() instanceof ToolBarButton) { + ToolBarButton button = (ToolBarButton) event.getTarget(); + String label = button.getLabel(); + + int index = labelList.indexOf(label); + if (index >= 0) { + setSelectedIndex(index); + } + } + } + + /** + * + * @param index + */ + public void setSelectedIndex(int index) { + selectedIndex = index; + render(index); + } + + private void render(int index) { + northBox.getChildren().clear(); + southBox.getChildren().clear(); + getCenter().getChildren().clear(); + + for (int i = 0; i < index; i++) { + Div div = new Div(); + div.setClass("z-center-header"); + div.appendChild(buttonList.get(i)); + div.setWidth("100%"); + northBox.appendChild(div); + } + + getCenter().setTitle(labelList.get(index)); + getCenter().appendChild(componentList.get(index)); + + for (int i = index + 1; i < labelList.size(); i++) { + Div div = new Div(); + div.setClass("z-center-header"); + div.appendChild(buttonList.get(i)); + div.setWidth("100%"); + southBox.appendChild(div); + } + + this.invalidate(); + } + + /** + * @param index + * @param tooltiptext + */ + public void setTooltiptext(int index, String tooltiptext) { + buttonList.get(index).setTooltiptext(tooltiptext); + } + +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/DPActivities.java b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPActivities.java similarity index 95% rename from zkwebui/WEB-INF/src/org/adempiere/webui/DPActivities.java rename to zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPActivities.java index ba2a1d430f..414357a0ff 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/DPActivities.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPActivities.java @@ -1,5 +1,6 @@ /****************************************************************************** * Copyright (C) 2008 Elaine Tan * + * Copyright (C) 2008 Idalica Corporation * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * @@ -10,7 +11,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * *****************************************************************************/ -package org.adempiere.webui; +package org.adempiere.webui.dashboard; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -161,7 +162,7 @@ public class DPActivities extends DashboardPanel implements EventListener { return count; } - public void updateInfo() + public void refresh() { int noOfNotice = getNoticeCount(); int noOfRequest = getRequestCount(); diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/DPCalendar.java b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPCalendar.java similarity index 90% rename from zkwebui/WEB-INF/src/org/adempiere/webui/DPCalendar.java rename to zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPCalendar.java index 0e17bfd953..08af21406e 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/DPCalendar.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPCalendar.java @@ -1,5 +1,6 @@ /****************************************************************************** * Copyright (C) 2008 Elaine Tan * + * Copyright (C) 2008 Idalica Corporation * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * @@ -10,7 +11,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * *****************************************************************************/ -package org.adempiere.webui; +package org.adempiere.webui.dashboard; import org.zkoss.zul.Iframe; diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/DPFavourites.java b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPFavourites.java similarity index 96% rename from zkwebui/WEB-INF/src/org/adempiere/webui/DPFavourites.java rename to zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPFavourites.java index 6595279bc8..1bb3388dae 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/DPFavourites.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPFavourites.java @@ -1,5 +1,6 @@ /****************************************************************************** * Copyright (C) 2008 Elaine Tan * + * Copyright (C) 2008 Idalica Corporation * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * @@ -10,7 +11,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * *****************************************************************************/ -package org.adempiere.webui; +package org.adempiere.webui.dashboard; import java.util.Enumeration; diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/DPPerformance.java b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPPerformance.java similarity index 92% rename from zkwebui/WEB-INF/src/org/adempiere/webui/DPPerformance.java rename to zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPPerformance.java index fa98c023d0..399ce127cf 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/DPPerformance.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPPerformance.java @@ -1,5 +1,6 @@ /****************************************************************************** * Copyright (C) 2008 Elaine Tan * + * Copyright (C) 2008 Idalica Corporation * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * @@ -10,7 +11,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * *****************************************************************************/ -package org.adempiere.webui; +package org.adempiere.webui.dashboard; import org.adempiere.webui.apps.graph.WPAPanel; diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/DPViews.java b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPViews.java similarity index 96% rename from zkwebui/WEB-INF/src/org/adempiere/webui/DPViews.java rename to zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPViews.java index 8d9a9a6de8..a9e2cfe4d5 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/DPViews.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DPViews.java @@ -1,5 +1,6 @@ /****************************************************************************** * Copyright (C) 2008 Elaine Tan * + * Copyright (C) 2008 Idalica Corporation * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * @@ -10,7 +11,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * *****************************************************************************/ -package org.adempiere.webui; +package org.adempiere.webui.dashboard; import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.component.ToolBarButton; diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/DashboardPanel.java b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DashboardPanel.java similarity index 88% rename from zkwebui/WEB-INF/src/org/adempiere/webui/DashboardPanel.java rename to zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DashboardPanel.java index ef549b9842..ad484f5eaa 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/DashboardPanel.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DashboardPanel.java @@ -1,5 +1,6 @@ /****************************************************************************** * Copyright (C) 2008 Elaine Tan * + * Copyright (C) 2008 Idalica Corporation * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * @@ -10,7 +11,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * *****************************************************************************/ -package org.adempiere.webui; +package org.adempiere.webui.dashboard; import org.adempiere.webui.component.Window; @@ -30,7 +31,7 @@ public abstract class DashboardPanel extends Window implements IDashboardPanel { * Desktop.UpdateInfoRunnable will call this method at a certain interval. * Subclass should overwrite this method to support server push. */ - public void updateInfo() { + public void refresh() { } diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java new file mode 100644 index 0000000000..19fd317454 --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java @@ -0,0 +1,83 @@ +/****************************************************************************** + * Copyright (C) 2008 Low Heng Sin * + * Copyright (C) 2008 Idalica Corporation * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.webui.dashboard; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; + +import org.adempiere.webui.desktop.IDesktop; +import org.compiere.util.CLogger; +import org.zkoss.zk.ui.Desktop; +import org.zkoss.zk.ui.Executions; + +public class DashboardRunnable implements Runnable { + private Desktop desktop; + private boolean stop = false; + private List dashboardPanels; + private IDesktop appDesktop; + + private static final CLogger logger = CLogger.getCLogger(DashboardRunnable.class); + + public DashboardRunnable(Desktop desktop, IDesktop appDesktop) { + this.desktop = desktop; + this.appDesktop = appDesktop; + + dashboardPanels = new ArrayList(); + } + + public void run() + { + while(!stop) { + try { + Thread.sleep(60000); // Update every one minutes + } catch (InterruptedException e1) { + if (stop) break; + } + + try { + // get full control of desktop + Executions.activate(desktop); + try { + refreshDashboard(); + } catch (Error ex) { + logger.log(Level.WARNING, "UpdateInfo Thread error="+ex.getLocalizedMessage(), ex); + break; + } finally { + // release full control of desktop + Executions.deactivate(desktop); + } + } catch (Throwable e) { + logger.log(Level.WARNING, "UpdateInfo Thread error="+e.getLocalizedMessage(), e); + break; + } + } + } + + public void refreshDashboard() + { + for(int i = 0; i < dashboardPanels.size(); i++) + dashboardPanels.get(i).refresh(); + + appDesktop.onServerPush(); + } + + public void stop() { + stop = true; + } + + public void add(DashboardPanel dashboardPanel) { + dashboardPanels.add(dashboardPanel); + } +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/IDashboardPanel.java b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/IDashboardPanel.java new file mode 100644 index 0000000000..547fc943e6 --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/IDashboardPanel.java @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright (C) 2008 Elaine Tan * + * Copyright (C) 2008 Idalica Corporation + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.webui.dashboard; + +/** + * Interface for dashboard panel + * @author Elaine + * @author hengsin + * + */ +public interface IDashboardPanel { + + /** + * Refresh content of panel + */ + public void refresh(); + +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/AbstractDesktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/AbstractDesktop.java new file mode 100644 index 0000000000..8d0d9b7981 --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/AbstractDesktop.java @@ -0,0 +1,393 @@ +/****************************************************************************** + * Copyright (C) 2008 Low Heng Sin * + * Copyright (C) 2008 Idalica Corporation * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.webui.desktop; + +import java.util.ArrayList; +import java.util.List; + +import org.adempiere.apps.graph.BarGraphColumn; +import org.adempiere.webui.ClientInfo; +import org.adempiere.webui.apps.AEnv; +import org.adempiere.webui.apps.graph.WBarGraph; +import org.adempiere.webui.component.Window; +import org.adempiere.webui.exception.ApplicationException; +import org.adempiere.webui.part.AbstractUIPart; +import org.compiere.model.MAchievement; +import org.compiere.model.MGoal; +import org.compiere.model.MMeasureCalc; +import org.compiere.model.MMenu; +import org.compiere.model.MProjectType; +import org.compiere.model.MQuery; +import org.compiere.model.MRequestType; +import org.compiere.model.MRole; +import org.compiere.util.CLogger; +import org.compiere.util.Env; +import org.zkoss.zhtml.Button; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zul.Panelchildren; + +/** + * Base class for desktop implementation + * @author hengsin + * + */ +public abstract class AbstractDesktop extends AbstractUIPart implements IDesktop { + + private transient ClientInfo clientInfo; + + private List windows = null; + + private MGoal[] m_goals = null; + + private List queryZoom = null; + + private static final CLogger logger = CLogger.getCLogger(AbstractDesktop.class); + + private static final String ZOOM_KEY = "queryZoom"; + + public AbstractDesktop() { + m_goals = MGoal.getUserGoals(Env.getCtx(), Env.getAD_User_ID(Env.getCtx())); + windows = new ArrayList(); + queryZoom = new ArrayList(); + } + + /** + * Event listener for menu item selection. + * Identifies the action associated with the selected + * menu item and acts accordingly. + * + * @param menuId Identifier for the selected menu item + * + * @throws ApplicationException If the selected menu action has yet + * to be implemented + */ + public void onMenuSelected(int menuId) + { + MMenu menu = new MMenu(Env.getCtx(), menuId, null); + if(menu == null) + { + return; + } + + if(menu.getAction().equals(MMenu.ACTION_Window)) + { + openWindow(menu.getAD_Window_ID()); + } + else if(menu.getAction().equals(MMenu.ACTION_Process) || + menu.getAction().equals(MMenu.ACTION_Report)) + { + openProcessDialog(menu.getAD_Process_ID(), menu.isSOTrx()); + } + else if(menu.getAction().equals(MMenu.ACTION_Form)) + { + openForm(menu.getAD_Form_ID()); + } + else if(menu.getAction().equals(MMenu.ACTION_WorkFlow)) + { + openWorkflow(menu.getAD_Workflow_ID()); + } + else if(menu.getAction().equals(MMenu.ACTION_Task)) + { + openTask(menu.getAD_Task_ID()); + } + else + { + throw new ApplicationException("Menu Action not yet implemented: " + menu.getAction()); + } + } + + /** + * @return clientInfo + */ + public ClientInfo getClientInfo() { + return clientInfo; + } + + /** + * + * @param clientInfo + */ + public void setClientInfo(ClientInfo clientInfo) { + this.clientInfo = clientInfo; + } + + /** + * @param win + */ + public int registerWindow(Object win) { + int retValue = windows.size(); + windows.add(win); + return retValue; + } + + /** + * @param WindowNo + */ + public void unregisterWindow(int WindowNo) { + if (WindowNo < windows.size()) + windows.set(WindowNo, null); + Env.clearWinContext(WindowNo); + } + + /** + * + * @param WindowNo + * @return Object + */ + public Object findWindow(int WindowNo) { + if (WindowNo < windows.size()) + return windows.get(WindowNo); + else + return null; + } + + /** + * @param win + */ + public void showWindow(Window win) + { + String pos = win.getPosition(); + this.showWindow(win, pos); + } + + /** + * @param win + * @param pos + */ + public void showWindow(Window win, String pos) + { + win.setPage(page); + Object objMode = win.getAttribute(Window.MODE_KEY); + + String mode = Window.MODE_MODAL; + + if (objMode != null) + { + mode = objMode.toString(); + } + + if (Window.MODE_MODAL.equals(mode)) + { + showModal(win); + } + else if (Window.MODE_POPUP.equals(mode)) + { + showPopup(win, pos); + } + else if (Window.MODE_OVERLAPPED.equals(mode)) + { + showOverlapped(win, pos); + } + else if (Window.MODE_EMBEDDED.equals(mode)) + { + showEmbedded(win); + } + else if (Window.MODE_HIGHLIGHTED.equals(mode)) + { + showHighlighted(win, pos); + } + } + + protected abstract void showEmbedded(Window win); + + /** + * + * @param win + */ + protected void showModal(Window win) + { + try + { + win.doModal(); + } + catch(InterruptedException e) + { + + } + + } + + /** + * + * @param win + * @param position + */ + protected void showPopup(Window win, String position) + { + if (position == null) + win.setPosition("center"); + else + win.setPosition(position); + + win.doPopup(); + } + + /** + * + * @param win + * @param position + */ + protected void showOverlapped(Window win, String position) + { + if (position == null) + win.setPosition("center"); + else + win.setPosition(position); + + win.doOverlapped(); + } + + /** + * + * @param win + * @param position + */ + protected void showHighlighted(Window win, String position) + { + if (position == null) + win.setPosition("center"); + else + win.setPosition(position); + + win.doHighlighted(); + } + + protected String renderGoals(int AD_Table_ID, Panelchildren panel) + { + String output = ""; + if (m_goals == null) + return output; + + for (int i = 0; i < m_goals.length; i++) + { + MMeasureCalc mc = MMeasureCalc.get(Env.getCtx(), m_goals[i].getMeasure().getPA_MeasureCalc_ID()); + + if (AD_Table_ID == m_goals[i].getPA_Goal_ID()) + { + output += "\n\n"; + output += "\n"; + output += "\n"; + + WBarGraph barPanel = new WBarGraph(m_goals[i]); + BarGraphColumn[] bList = barPanel.getBarGraphColumnList(); + MQuery query = null; + output += "\n"; + + for (int k = 0; k < bList.length; k++) + { + BarGraphColumn bgc = bList[k]; + if (k > 0) + output += ""; + if (bgc.getAchievement() != null) // Single Achievement + { + MAchievement a = bgc.getAchievement(); + query = MQuery.getEqualQuery("PA_Measure_ID", a.getPA_Measure_ID()); + } + else if (bgc.getGoal() != null) // Multiple Achievements + { + MGoal goal = bgc.getGoal(); + query = MQuery.getEqualQuery("PA_Measure_ID", goal.getPA_Measure_ID()); + } + else if (bgc.getMeasureCalc() != null) // Document + { + mc = bgc.getMeasureCalc(); + query = mc.getQuery(m_goals[i].getRestrictions(false), bgc.getMeasureDisplay(), + bgc.getDate(), MRole.getDefault()); // logged in role + } + else if (bgc.getProjectType() != null) // Document + { + MProjectType pt = bgc.getProjectType(); + query = pt.getQuery(m_goals[i].getRestrictions(false), bgc.getMeasureDisplay(), + bgc.getDate(), bgc.getID(), MRole.getDefault()); // logged in role + } + else if (bgc.getRequestType() != null) // Document + { + MRequestType rt = bgc.getRequestType(); + query = rt.getQuery(m_goals[i].getRestrictions(false), bgc.getMeasureDisplay(), + bgc.getDate(), bgc.getID(), MRole.getDefault()); // logged in role + } + output += ""; + } + output += "" + + "" + + "
" + + m_goals[i].getName() + "
Target" + + m_goals[i].getMeasureTarget() + "
Actual" + + m_goals[i].getMeasureActual() + "
" + + m_goals[i].getXAxisText() + "
" + bgc.getLabel() + + ""; + if (query != null) { + Button btn = new Button(); + btn.setId(String.valueOf(ZOOM_KEY + queryZoom.size())); + btn.addEventListener(Events.ON_CLICK, new EventListener() { + public void onEvent(Event event) throws Exception { + Component comp = event.getTarget(); + String id = comp.getId(); + if(id.startsWith(ZOOM_KEY)) + { + String ss = id.substring(ZOOM_KEY.length()); + int index = Integer.parseInt(String.valueOf(ss)); + if ((index >= 0) && (index < queryZoom.size())) + AEnv.zoom(queryZoom.get(index)); + } + } + + }); + btn.setVisible(false); + panel.appendChild(btn); + + output += "" + + bgc.getValue() + + "
\n"; + + queryZoom.add(query); + } else { + logger.info("Nothing to zoom to - " + bgc); + output += bgc.getValue(); + } + output += "
" + + m_goals[i].getDescription() + + "
" + + stripHtml(m_goals[i].getColorSchema() + .getDescription(), true) + "
\n"; + bList = null; + barPanel = null; + } + } + + return output; + } + + protected String stripHtml(String htmlString, boolean all) { + htmlString = htmlString + .replace("", "") + .replace("", "") + .replace("", "") + .replace("", "") + .replace("", "") + .replace("", ""); + + if (all) + htmlString = htmlString + .replace(">", ">") + .replace("<", "<"); + return htmlString; + } +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java new file mode 100644 index 0000000000..0fef588406 --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java @@ -0,0 +1,385 @@ +/****************************************************************************** + * Product: Posterita Ajax UI * + * Copyright (C) 2007 Posterita Ltd. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * Posterita Ltd., 3, Draper Avenue, Quatre Bornes, Mauritius * + * or via info@posterita.org or http://www.posterita.org/ * + *****************************************************************************/ + +package org.adempiere.webui.desktop; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.net.URL; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.logging.Level; + +import org.adempiere.webui.component.Tabpanel; +import org.adempiere.webui.component.ToolBarButton; +import org.adempiere.webui.dashboard.DPActivities; +import org.adempiere.webui.dashboard.DashboardPanel; +import org.adempiere.webui.dashboard.DashboardRunnable; +import org.adempiere.webui.event.MenuListener; +import org.adempiere.webui.panel.HeaderPanel; +import org.adempiere.webui.panel.SidePanel; +import org.compiere.model.MMenu; +import org.compiere.model.X_AD_Menu; +import org.compiere.model.X_PA_DashboardContent; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Env; +import org.compiere.util.Msg; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.Page; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zkex.zul.Borderlayout; +import org.zkoss.zkex.zul.Center; +import org.zkoss.zkex.zul.North; +import org.zkoss.zkex.zul.West; +import org.zkoss.zkmax.zul.Portalchildren; +import org.zkoss.zkmax.zul.Portallayout; +import org.zkoss.zul.Html; +import org.zkoss.zul.Panel; +import org.zkoss.zul.Panelchildren; + +/** + * + * Default desktop implementation. + * @author Ashley G Ramdass + * @author Low Heng Sin + * @date Mar 2, 2007 + * @version $Revision: 0.10 $ + */ +public class DefaultDesktop extends TabbedDesktop implements MenuListener, Serializable, EventListener +{ + + private static final long serialVersionUID = 9056511175189603883L; + + private static final CLogger logger = CLogger.getCLogger(DefaultDesktop.class); + + private Center windowArea; + + private Borderlayout layout; + + private Thread dashboardThread; + + private DashboardRunnable dashboardRunnable; + + public DefaultDesktop() + { + super(); + } + + protected Component doCreatePart(Component parent) + { + SidePanel pnlSide = new SidePanel(); + HeaderPanel pnlHead = new HeaderPanel(); + + pnlSide.getMenuPanel().addMenuListener(this); + + layout = new Borderlayout(); + if (parent != null) + { + layout.setParent(parent); + layout.setWidth("100%"); + layout.setHeight("100%"); + layout.setStyle("position: absolute"); + } + else + layout.setPage(page); + + dashboardRunnable = new DashboardRunnable(layout.getDesktop(), this); + + North n = new North(); + layout.appendChild(n); + n.setCollapsible(false); + pnlHead.setParent(n); + + West w = new West(); + layout.appendChild(w); + w.setWidth("300px"); + w.setCollapsible(true); + w.setSplittable(true); + w.setTitle("Menu"); + w.setFlex(true); + pnlSide.setParent(w); + + windowArea = new Center(); + windowArea.setParent(layout); + windowArea.setFlex(true); + + windowContainer.createPart(windowArea); + + createHomeTab(); + + return layout; + } + + private void createHomeTab() + { + Tabpanel homeTab = new Tabpanel(); + windowContainer.addWindow(homeTab, Msg.getMsg(Env.getCtx(), "Home").replaceAll("&", ""), false); + + Portallayout portalLayout = new Portallayout(); + portalLayout.setWidth("100%"); + homeTab.appendChild(portalLayout); + + // Dashboard content + Portalchildren portalchildren = null; + int currentColumnNo = 0; + + String sql = "SELECT COUNT(DISTINCT COLUMNNO) " + + "FROM PA_DASHBOARDCONTENT " + + "WHERE (AD_CLIENT_ID=0 OR AD_CLIENT_ID=?) AND ISACTIVE='Y'"; + + int noOfCols = DB.getSQLValue(null, sql, + Env.getAD_Client_ID(Env.getCtx())); + + int width = noOfCols <= 0 ? 100 : 100/noOfCols; + + sql = "SELECT x.*, m.AD_MENU_ID " + + "FROM PA_DASHBOARDCONTENT x " + + "LEFT OUTER JOIN AD_MENU m ON x.AD_WINDOW_ID=m.AD_WINDOW_ID " + + "WHERE (x.AD_CLIENT_ID=0 OR x.AD_CLIENT_ID=?) AND x.ISACTIVE='Y' " + + "ORDER BY x.COLUMNNO, x.AD_CLIENT_ID, x.LINE "; + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, Env.getAD_Client_ID(Env.getCtx())); + rs = pstmt.executeQuery(); + + while (rs.next()) + { + int columnNo = rs.getInt(X_PA_DashboardContent.COLUMNNAME_ColumnNo); + if(portalchildren == null || currentColumnNo != columnNo) + { + portalchildren = new Portalchildren(); + portalLayout.appendChild(portalchildren); + portalchildren.setWidth(width + "%"); + portalchildren.setStyle("padding: 5px"); + + currentColumnNo = columnNo; + } + + Panel panel = new Panel(); + panel.setStyle("margin-bottom:10px"); + panel.setTitle(rs.getString(X_PA_DashboardContent.COLUMNNAME_Name)); + + String description = rs.getString(X_PA_DashboardContent.COLUMNNAME_Description); + if(description != null) + panel.setTooltiptext(description); + + String collapsible = rs.getString(X_PA_DashboardContent.COLUMNNAME_IsCollapsible); + panel.setCollapsible(collapsible.equals("Y")); + + panel.setBorder("normal"); + portalchildren.appendChild(panel); + Panelchildren content = new Panelchildren(); + panel.appendChild(content); + + boolean panelEmpty = true; + + // HTML content + String htmlContent = rs.getString(X_PA_DashboardContent.COLUMNNAME_HTML); + if(htmlContent != null) + { + StringBuffer result = new StringBuffer(""); + + URL url = getClass().getClassLoader(). + getResource("org/compiere/images/PAPanel.css"); + InputStreamReader ins; + try { + ins = new InputStreamReader(url.openStream()); + BufferedReader bufferedReader = new BufferedReader( ins ); + String cssLine; + while ((cssLine = bufferedReader.readLine()) != null) + result.append(cssLine + "\n"); + } catch (IOException e1) { + logger.log(Level.SEVERE, e1.getLocalizedMessage(), e1); + } + + result.append("
\n"); + +// if(description != null) +// result.append("

" + description + "

\n"); + result.append(stripHtml(htmlContent, false) + "
\n"); + result.append("
\n\n\n"); + + Html html = new Html(); + html.setContent(result.toString()); + content.appendChild(html); + panelEmpty = false; + } + + // Window + int AD_Window_ID = rs.getInt(X_PA_DashboardContent.COLUMNNAME_AD_Window_ID); + if(AD_Window_ID > 0) + { + int AD_Menu_ID = rs.getInt(X_AD_Menu.COLUMNNAME_AD_Menu_ID); + ToolBarButton btn = new ToolBarButton(String.valueOf(AD_Menu_ID)); + MMenu menu = new MMenu(Env.getCtx(), AD_Menu_ID, null); + btn.setLabel(menu.getName()); + btn.addEventListener(Events.ON_CLICK, this); + content.appendChild(btn); + panelEmpty = false; + } + + // Goal + int PA_Goal_ID = rs.getInt(X_PA_DashboardContent.COLUMNNAME_PA_Goal_ID); + if(PA_Goal_ID > 0) + { + StringBuffer result = new StringBuffer(""); + + URL url = getClass().getClassLoader(). + getResource("org/compiere/images/PAPanel.css"); + InputStreamReader ins; + try { + ins = new InputStreamReader(url.openStream()); + BufferedReader bufferedReader = new BufferedReader( ins ); + String cssLine; + while ((cssLine = bufferedReader.readLine()) != null) + result.append(cssLine + "\n"); + } catch (IOException e1) { + logger.log(Level.SEVERE, e1.getLocalizedMessage(), e1); + } + + result.append("
\n"); + result.append(renderGoals(PA_Goal_ID, content)); + result.append("
\n\n\n"); + + Html html = new Html(); + html.setContent(result.toString()); + content.appendChild(html); + panelEmpty = false; + } + + // ZUL file url + String url = rs.getString(X_PA_DashboardContent.COLUMNNAME_ZulFilePath); + if(url != null) + { + try { + Component component = Executions.createComponents(url, content, null); + if(component != null) + { + if (component instanceof DashboardPanel) + { + DashboardPanel dashboardPanel = (DashboardPanel) component; + if (!dashboardPanel.getChildren().isEmpty()) { + content.appendChild(dashboardPanel); + dashboardRunnable.add(dashboardPanel); + panelEmpty = false; + } + } + else + { + content.appendChild(component); + panelEmpty = false; + } + } + } catch (Exception e) { + logger.log(Level.WARNING, "Failed to create components. zul="+url, e); + } + } + + if (panelEmpty) + panel.detach(); + } + } catch(Exception e) { + logger.log(Level.WARNING, "Failed to create dashboard content", e); + } finally { + DB.close(rs, pstmt); + } + // + + //register as 0 + registerWindow(homeTab); + + if (!portalLayout.getDesktop().isServerPushEnabled()) + portalLayout.getDesktop().enableServerPush(true); + + dashboardRunnable.refreshDashboard(); + + dashboardThread = new Thread(dashboardRunnable, "UpdateInfo"); + dashboardThread.setDaemon(true); + dashboardThread.start(); + } + + public void onEvent(Event event) + { + Component comp = event.getTarget(); + String eventName = event.getName(); + + if(eventName.equals(Events.ON_CLICK)) + { + if(comp instanceof ToolBarButton) + { + ToolBarButton btn = (ToolBarButton) comp; + + int menuId = 0; + try + { + menuId = Integer.valueOf(btn.getName()); + } + catch (Exception e) { + + } + + if(menuId > 0) onMenuSelected(menuId); + } + } + } + + public void onServerPush() + { + int noOfNotice = DPActivities.getNoticeCount(); + int noOfRequest = DPActivities.getRequestCount(); + int noOfWorkflow = DPActivities.getWorkflowCount(); + int total = noOfNotice + noOfRequest + noOfWorkflow; + + windowContainer.setTabTitle(0, "Home (" + total + ")", + "Notice : " + noOfNotice + ", Request : " + noOfRequest + ", Workflow Activities : " + noOfWorkflow); + } + + /** + * + * @param page + */ + public void setPage(Page page) { + if (this.page != page) { + layout.setPage(page); + this.page = page; + } + } + + /** + * Get the root component + * @return Component + */ + public Component getComponent() { + return layout; + } + + public void logout() { + if (dashboardThread != null && dashboardThread.isAlive()) { + dashboardRunnable.stop(); + dashboardThread.interrupt(); + } + } +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/IDesktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/IDesktop.java new file mode 100644 index 0000000000..d574eb5dfa --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/IDesktop.java @@ -0,0 +1,177 @@ +/****************************************************************************** + * Copyright (C) 2008 Low Heng Sin * + * Copyright (C) 2008 Idalica Corporation * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.webui.desktop; + +import org.adempiere.webui.ClientInfo; +import org.adempiere.webui.apps.ProcessDialog; +import org.adempiere.webui.component.Window; +import org.adempiere.webui.panel.ADForm; +import org.adempiere.webui.part.UIPart; +import org.adempiere.webui.window.ADWindow; +import org.compiere.model.MQuery; +import org.compiere.util.WebDoc; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.Page; + +/** + * Desktop interface + * @author hengsin + * + */ +public interface IDesktop extends UIPart { + + public static final String WINDOWNO_ATTRIBUTE = "desktop.windowno"; + public static final String CLASS_NAME_KEY = "ZK_DESKTOP_CLASS"; + + /** + * + * @return ClientInfo + */ + public ClientInfo getClientInfo(); + + /** + * + * @param nodeId + */ + public void onMenuSelected(int nodeId); + + /** + * + * @param window + * @return windowNo + */ + public int registerWindow(Object window); + + /** + * + * @param WindowNo + * @return Object + */ + public Object findWindow(int WindowNo); + + /** + * close active window + * @return boolean + */ + public boolean closeActiveWindow(); + + /** + * + * @param windowNo + * @return boolean + */ + public boolean closeWindow(int windowNo); + + /** + * + * @param url + * @param closeable + */ + public void showURL(String url, boolean closeable); + + /** + * + * @param doc + * @param string + * @param closeable + */ + public void showURL(WebDoc doc, String string, boolean closeable); + + /** + * + * @param win + */ + public void showWindow(Window win); + + /** + * + * @param win + * @param position + */ + public void showWindow(Window win, String position); + + /** + * + * @param window_ID + * @param query + */ + public void showZoomWindow(int window_ID, MQuery query); + + /** + * + * @param windowNo + */ + public void unregisterWindow(int windowNo); + + /** + * + * @param processId + * @param soTrx + * @return ProcessDialog + */ + public ProcessDialog openProcessDialog(int processId, boolean soTrx); + + /** + * + * @param formId + * @return ADWindow + */ + public ADForm openForm(int formId); + + /** + * + * @param windowId + * @return ADWindow + */ + public ADWindow openWindow(int windowId); + + /** + * Open operating system task window + * @param task_ID + */ + public void openTask(int task_ID); + + /** + * + * @param workflow_ID + */ + public void openWorkflow(int workflow_ID); + + /** + * Get the root component of the desktop + * @return Component + */ + public Component getComponent(); + + /** + * Attached to page + * @param page + */ + public void setPage(Page page); + + /** + * @param clientInfo + */ + public void setClientInfo(ClientInfo clientInfo); + + /** + * User logout from desktop, do clean up + */ + public void logout(); + + /** + * Invoke by the server push thread. + */ + public void onServerPush(); +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/LeftBar2Desktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/LeftBar2Desktop.java new file mode 100644 index 0000000000..eb7591fadd --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/LeftBar2Desktop.java @@ -0,0 +1,425 @@ +/****************************************************************************** + * Copyright (C) 2008 Low Heng Sin * + * Copyright (C) 2008 Idalica Corporation * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.webui.desktop; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.net.URL; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.logging.Level; + +import org.adempiere.webui.component.Accordion; +import org.adempiere.webui.component.Tabpanel; +import org.adempiere.webui.component.ToolBarButton; +import org.adempiere.webui.dashboard.DPActivities; +import org.adempiere.webui.dashboard.DashboardPanel; +import org.adempiere.webui.dashboard.DashboardRunnable; +import org.adempiere.webui.event.MenuListener; +import org.adempiere.webui.panel.HeaderPanel; +import org.adempiere.webui.panel.SidePanel; +import org.compiere.model.MMenu; +import org.compiere.model.X_AD_Menu; +import org.compiere.model.X_PA_DashboardContent; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Env; +import org.compiere.util.Msg; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.Page; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zkex.zul.Borderlayout; +import org.zkoss.zkex.zul.Center; +import org.zkoss.zkex.zul.North; +import org.zkoss.zkex.zul.West; +import org.zkoss.zkmax.zul.Portalchildren; +import org.zkoss.zkmax.zul.Portallayout; +import org.zkoss.zul.Div; +import org.zkoss.zul.Html; +import org.zkoss.zul.Panel; +import org.zkoss.zul.Panelchildren; + +/** + * @author hengsin + */ +public class LeftBar2Desktop extends TabbedDesktop implements MenuListener, Serializable, EventListener +{ + + private static final String FAVOURITES_PATH = "/zul/favourites.zul"; + + private static final String ACTIVITIES_PATH = "/zul/activities.zul"; + + private static final long serialVersionUID = 9056511175189603883L; + + private static final CLogger logger = CLogger.getCLogger(DefaultDesktop.class); + + private Center windowArea; + + private Borderlayout layout; + + private Thread dashboardThread; + + private DashboardRunnable dashboardRunnable; + + private Accordion shortcutPanel; + + public LeftBar2Desktop() + { + super(); + } + + protected Component doCreatePart(Component parent) + { + SidePanel pnlSide = new SidePanel(); + HeaderPanel pnlHead = new HeaderPanel(); + + pnlSide.getMenuPanel().addMenuListener(this); + + layout = new Borderlayout(); + if (parent != null) + { + layout.setParent(parent); + layout.setWidth("100%"); + layout.setHeight("100%"); + layout.setStyle("position: absolute"); + } + else + layout.setPage(page); + + dashboardRunnable = new DashboardRunnable(layout.getDesktop(), this); + + North n = new North(); + layout.appendChild(n); + n.setCollapsible(false); + pnlHead.setParent(n); + + West w = new West(); + layout.appendChild(w); + w.setWidth("300px"); + w.setCollapsible(true); + w.setSplittable(true); + w.setTitle("Menu"); + w.setFlex(true); + pnlSide.setParent(w); + w.setOpen(false); + + Center center = new Center(); + center.setParent(layout); + center.setFlex(true); + + Borderlayout innerLayout = new Borderlayout(); + innerLayout.setHeight("100%"); + innerLayout.setWidth("100%"); + innerLayout.setParent(center); + + West innerW = new West(); + innerW.setWidth("200px"); + innerW.setCollapsible(true); + innerW.setTitle("Navigation"); + innerW.setSplittable(true); + innerW.setCollapsible(true); + innerW.setParent(innerLayout); + + shortcutPanel = new Accordion(); + shortcutPanel.setWidth("100%"); + shortcutPanel.setHeight("100%"); + innerW.appendChild(shortcutPanel); + + Div div = new Div(); + Executions.createComponents(FAVOURITES_PATH, div, null); + shortcutPanel.add(div, "Favourites"); + + div = new Div(); + Component component = Executions.createComponents(ACTIVITIES_PATH, div, null); + if (component instanceof DashboardPanel) + { + DashboardPanel dashboardPanel = (DashboardPanel) component; + dashboardRunnable.add(dashboardPanel); + } + shortcutPanel.add(div, "Activities"); + + shortcutPanel.setSelectedIndex(0); + + windowArea = new Center(); + windowArea.setParent(innerLayout); + windowArea.setFlex(true); + + windowContainer.createPart(windowArea); + + createHomeTab(); + + return layout; + } + + private void createHomeTab() + { + Tabpanel homeTab = new Tabpanel(); + windowContainer.addWindow(homeTab, Msg.getMsg(Env.getCtx(), "Home").replaceAll("&", ""), false); + + Portallayout portalLayout = new Portallayout(); + portalLayout.setWidth("100%"); + homeTab.appendChild(portalLayout); + + // Dashboard content + Portalchildren portalchildren = null; + int currentColumnNo = 0; + + String sql = "SELECT COUNT(DISTINCT COLUMNNO) " + + "FROM PA_DASHBOARDCONTENT " + + "WHERE (AD_CLIENT_ID=0 OR AD_CLIENT_ID=?) AND ISACTIVE='Y'"; + + int noOfCols = DB.getSQLValue(null, sql, + Env.getAD_Client_ID(Env.getCtx())); + + int width = noOfCols <= 0 ? 100 : 100/noOfCols; + + sql = "SELECT x.*, m.AD_MENU_ID " + + "FROM PA_DASHBOARDCONTENT x " + + "LEFT OUTER JOIN AD_MENU m ON x.AD_WINDOW_ID=m.AD_WINDOW_ID " + + "WHERE (x.AD_CLIENT_ID=0 OR x.AD_CLIENT_ID=?) AND x.ISACTIVE='Y' " + + "AND x.zulfilepath not in (?, ?) " + + "ORDER BY x.COLUMNNO, x.AD_CLIENT_ID, x.LINE "; + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, Env.getAD_Client_ID(Env.getCtx())); + pstmt.setString(2, ACTIVITIES_PATH); + pstmt.setString(3, FAVOURITES_PATH); + rs = pstmt.executeQuery(); + + while (rs.next()) + { + int columnNo = rs.getInt(X_PA_DashboardContent.COLUMNNAME_ColumnNo); + if(portalchildren == null || currentColumnNo != columnNo) + { + portalchildren = new Portalchildren(); + portalLayout.appendChild(portalchildren); + portalchildren.setWidth(width + "%"); + portalchildren.setStyle("padding: 5px"); + + currentColumnNo = columnNo; + } + + Panel panel = new Panel(); + panel.setStyle("margin-bottom:10px"); + panel.setTitle(rs.getString(X_PA_DashboardContent.COLUMNNAME_Name)); + + String description = rs.getString(X_PA_DashboardContent.COLUMNNAME_Description); + if(description != null) + panel.setTooltiptext(description); + + String collapsible = rs.getString(X_PA_DashboardContent.COLUMNNAME_IsCollapsible); + panel.setCollapsible(collapsible.equals("Y")); + + panel.setBorder("normal"); + portalchildren.appendChild(panel); + Panelchildren content = new Panelchildren(); + panel.appendChild(content); + + boolean panelEmpty = true; + + // HTML content + String htmlContent = rs.getString(X_PA_DashboardContent.COLUMNNAME_HTML); + if(htmlContent != null) + { + StringBuffer result = new StringBuffer(""); + + URL url = getClass().getClassLoader(). + getResource("org/compiere/images/PAPanel.css"); + InputStreamReader ins; + try { + ins = new InputStreamReader(url.openStream()); + BufferedReader bufferedReader = new BufferedReader( ins ); + String cssLine; + while ((cssLine = bufferedReader.readLine()) != null) + result.append(cssLine + "\n"); + } catch (IOException e1) { + logger.log(Level.SEVERE, e1.getLocalizedMessage(), e1); + } + + result.append("
\n"); + +// if(description != null) +// result.append("

" + description + "

\n"); + result.append(stripHtml(htmlContent, false) + "
\n"); + result.append("
\n\n\n"); + + Html html = new Html(); + html.setContent(result.toString()); + content.appendChild(html); + panelEmpty = false; + } + + // Window + int AD_Window_ID = rs.getInt(X_PA_DashboardContent.COLUMNNAME_AD_Window_ID); + if(AD_Window_ID > 0) + { + int AD_Menu_ID = rs.getInt(X_AD_Menu.COLUMNNAME_AD_Menu_ID); + ToolBarButton btn = new ToolBarButton(String.valueOf(AD_Menu_ID)); + MMenu menu = new MMenu(Env.getCtx(), AD_Menu_ID, null); + btn.setLabel(menu.getName()); + btn.addEventListener(Events.ON_CLICK, this); + content.appendChild(btn); + panelEmpty = false; + } + + // Goal + int PA_Goal_ID = rs.getInt(X_PA_DashboardContent.COLUMNNAME_PA_Goal_ID); + if(PA_Goal_ID > 0) + { + StringBuffer result = new StringBuffer(""); + + URL url = getClass().getClassLoader(). + getResource("org/compiere/images/PAPanel.css"); + InputStreamReader ins; + try { + ins = new InputStreamReader(url.openStream()); + BufferedReader bufferedReader = new BufferedReader( ins ); + String cssLine; + while ((cssLine = bufferedReader.readLine()) != null) + result.append(cssLine + "\n"); + } catch (IOException e1) { + logger.log(Level.SEVERE, e1.getLocalizedMessage(), e1); + } + + result.append("
\n"); + result.append(renderGoals(PA_Goal_ID, content)); + result.append("
\n\n\n"); + + Html html = new Html(); + html.setContent(result.toString()); + content.appendChild(html); + panelEmpty = false; + } + + // ZUL file url + String url = rs.getString(X_PA_DashboardContent.COLUMNNAME_ZulFilePath); + if(url != null) + { + try { + Component component = Executions.createComponents(url, content, null); + if(component != null) + { + if (component instanceof DashboardPanel) + { + DashboardPanel dashboardPanel = (DashboardPanel) component; + if (!dashboardPanel.getChildren().isEmpty()) { + content.appendChild(dashboardPanel); + dashboardRunnable.add(dashboardPanel); + panelEmpty = false; + } + } + else + { + content.appendChild(component); + panelEmpty = false; + } + } + } catch (Exception e) { + logger.log(Level.WARNING, "Failed to create components. zul="+url, e); + } + } + + if (panelEmpty) + panel.detach(); + } + } catch(Exception e) { + logger.log(Level.WARNING, "Failed to create dashboard content", e); + } finally { + DB.close(rs, pstmt); + } + // + + //register as 0 + registerWindow(homeTab); + + if (!portalLayout.getDesktop().isServerPushEnabled()) + portalLayout.getDesktop().enableServerPush(true); + + dashboardRunnable.refreshDashboard(); + + dashboardThread = new Thread(dashboardRunnable, "UpdateInfo"); + dashboardThread.setDaemon(true); + dashboardThread.start(); + } + + public void onEvent(Event event) + { + Component comp = event.getTarget(); + String eventName = event.getName(); + + if(eventName.equals(Events.ON_CLICK)) + { + if(comp instanceof ToolBarButton) + { + ToolBarButton btn = (ToolBarButton) comp; + + int menuId = 0; + try + { + menuId = Integer.valueOf(btn.getName()); + } + catch (Exception e) { + + } + + if(menuId > 0) onMenuSelected(menuId); + } + } + } + + public void onServerPush() + { + int noOfNotice = DPActivities.getNoticeCount(); + int noOfRequest = DPActivities.getRequestCount(); + int noOfWorkflow = DPActivities.getWorkflowCount(); + int total = noOfNotice + noOfRequest + noOfWorkflow; + + shortcutPanel.setLabel(1, "Activities (" + total + ")"); + shortcutPanel.setTooltiptext(1, "Notice : " + noOfNotice + ", Request : " + noOfRequest + ", Workflow Activities : " + noOfWorkflow); + } + + /** + * + * @param page + */ + public void setPage(Page page) { + if (this.page != page) { + layout.setPage(page); + this.page = page; + } + } + + /** + * Get the root component + * @return Component + */ + public Component getComponent() { + return layout; + } + + public void logout() { + if (dashboardThread != null && dashboardThread.isAlive()) { + dashboardRunnable.stop(); + dashboardThread.interrupt(); + } + } +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/LeftBarDesktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/LeftBarDesktop.java new file mode 100644 index 0000000000..58eb9e3e51 --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/LeftBarDesktop.java @@ -0,0 +1,417 @@ +/****************************************************************************** + * Copyright (C) 2008 Low Heng Sin * + * Copyright (C) 2008 Idalica Corporation * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.webui.desktop; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.net.URL; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.logging.Level; + +import org.adempiere.webui.component.Accordion; +import org.adempiere.webui.component.Tabpanel; +import org.adempiere.webui.component.ToolBarButton; +import org.adempiere.webui.dashboard.DPActivities; +import org.adempiere.webui.dashboard.DashboardPanel; +import org.adempiere.webui.dashboard.DashboardRunnable; +import org.adempiere.webui.event.MenuListener; +import org.adempiere.webui.panel.HeaderPanel; +import org.adempiere.webui.panel.SidePanel; +import org.compiere.model.MMenu; +import org.compiere.model.X_AD_Menu; +import org.compiere.model.X_PA_DashboardContent; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Env; +import org.compiere.util.Msg; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.Page; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zkex.zul.Borderlayout; +import org.zkoss.zkex.zul.Center; +import org.zkoss.zkex.zul.North; +import org.zkoss.zkex.zul.West; +import org.zkoss.zkmax.zul.Portalchildren; +import org.zkoss.zkmax.zul.Portallayout; +import org.zkoss.zul.Div; +import org.zkoss.zul.Html; +import org.zkoss.zul.Panel; +import org.zkoss.zul.Panelchildren; + +/** + * @author hengsin + */ +public class LeftBarDesktop extends TabbedDesktop implements MenuListener, Serializable, EventListener +{ + + private static final String FAVOURITES_PATH = "/zul/favourites.zul"; + + private static final String ACTIVITIES_PATH = "/zul/activities.zul"; + + private static final String VIEWS_PATH = "/zul/views.zul"; + + private static final long serialVersionUID = 9056511175189603883L; + + private static final CLogger logger = CLogger.getCLogger(DefaultDesktop.class); + + private Center windowArea; + + private Borderlayout layout; + + private Thread dashboardThread; + + private DashboardRunnable dashboardRunnable; + + private Accordion navigationPanel; + + private West leftRegion; + + public LeftBarDesktop() + { + super(); + } + + protected Component doCreatePart(Component parent) + { + SidePanel pnlSide = new SidePanel(); + HeaderPanel pnlHead = new HeaderPanel(); + + pnlSide.getMenuPanel().addMenuListener(this); + + layout = new Borderlayout(); + if (parent != null) + { + layout.setParent(parent); + layout.setWidth("100%"); + layout.setHeight("100%"); + layout.setStyle("position: absolute"); + } + else + layout.setPage(page); + + dashboardRunnable = new DashboardRunnable(layout.getDesktop(), this); + + North n = new North(); + layout.appendChild(n); + n.setCollapsible(false); + pnlHead.setParent(n); + + leftRegion = new West(); + layout.appendChild(leftRegion); + leftRegion.setWidth("300px"); + leftRegion.setCollapsible(true); + leftRegion.setSplittable(true); + leftRegion.setTitle("Navigation"); + leftRegion.setFlex(true); + navigationPanel = new Accordion(); + navigationPanel.setParent(leftRegion); + leftRegion.setOpen(true); + + navigationPanel.setWidth("100%"); + navigationPanel.setHeight("100%"); + navigationPanel.add(pnlSide, "Application Menu"); + + Div div = new Div(); + Executions.createComponents(FAVOURITES_PATH, div, null); + navigationPanel.add(div, "Favourites"); + + div = new Div(); + Component component = Executions.createComponents(ACTIVITIES_PATH, div, null); + if (component instanceof DashboardPanel) + { + DashboardPanel dashboardPanel = (DashboardPanel) component; + dashboardRunnable.add(dashboardPanel); + } + navigationPanel.add(div, "Activities"); + + div = new Div(); + Executions.createComponents(VIEWS_PATH, div, null); + navigationPanel.add(div, "Views"); + + navigationPanel.setSelectedIndex(0); + + windowArea = new Center(); + windowArea.setParent(layout); + windowArea.setFlex(true); + + windowContainer.createPart(windowArea); + + createHomeTab(); + + return layout; + } + + private void createHomeTab() + { + Tabpanel homeTab = new Tabpanel(); + windowContainer.addWindow(homeTab, Msg.getMsg(Env.getCtx(), "Home").replaceAll("&", ""), false); + + Portallayout portalLayout = new Portallayout(); + portalLayout.setWidth("100%"); + homeTab.appendChild(portalLayout); + + // Dashboard content + Portalchildren portalchildren = null; + int currentColumnNo = 0; + + String sql = "SELECT COUNT(DISTINCT COLUMNNO) " + + "FROM PA_DASHBOARDCONTENT " + + "WHERE (AD_CLIENT_ID=0 OR AD_CLIENT_ID=?) AND ISACTIVE='Y'"; + + int noOfCols = DB.getSQLValue(null, sql, + Env.getAD_Client_ID(Env.getCtx())); + + int width = noOfCols <= 0 ? 100 : 100/noOfCols; + + sql = "SELECT x.*, m.AD_MENU_ID " + + "FROM PA_DASHBOARDCONTENT x " + + "LEFT OUTER JOIN AD_MENU m ON x.AD_WINDOW_ID=m.AD_WINDOW_ID " + + "WHERE (x.AD_CLIENT_ID=0 OR x.AD_CLIENT_ID=?) AND x.ISACTIVE='Y' " + + "AND x.zulfilepath not in (?, ?, ?) " + + "ORDER BY x.COLUMNNO, x.AD_CLIENT_ID, x.LINE "; + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, Env.getAD_Client_ID(Env.getCtx())); + pstmt.setString(2, ACTIVITIES_PATH); + pstmt.setString(3, FAVOURITES_PATH); + pstmt.setString(4, VIEWS_PATH); + rs = pstmt.executeQuery(); + + while (rs.next()) + { + int columnNo = rs.getInt(X_PA_DashboardContent.COLUMNNAME_ColumnNo); + if(portalchildren == null || currentColumnNo != columnNo) + { + portalchildren = new Portalchildren(); + portalLayout.appendChild(portalchildren); + portalchildren.setWidth(width + "%"); + portalchildren.setStyle("padding: 5px"); + + currentColumnNo = columnNo; + } + + Panel panel = new Panel(); + panel.setStyle("margin-bottom:10px"); + panel.setTitle(rs.getString(X_PA_DashboardContent.COLUMNNAME_Name)); + + String description = rs.getString(X_PA_DashboardContent.COLUMNNAME_Description); + if(description != null) + panel.setTooltiptext(description); + + String collapsible = rs.getString(X_PA_DashboardContent.COLUMNNAME_IsCollapsible); + panel.setCollapsible(collapsible.equals("Y")); + + panel.setBorder("normal"); + portalchildren.appendChild(panel); + Panelchildren content = new Panelchildren(); + panel.appendChild(content); + + boolean panelEmpty = true; + + // HTML content + String htmlContent = rs.getString(X_PA_DashboardContent.COLUMNNAME_HTML); + if(htmlContent != null) + { + StringBuffer result = new StringBuffer(""); + + URL url = getClass().getClassLoader(). + getResource("org/compiere/images/PAPanel.css"); + InputStreamReader ins; + try { + ins = new InputStreamReader(url.openStream()); + BufferedReader bufferedReader = new BufferedReader( ins ); + String cssLine; + while ((cssLine = bufferedReader.readLine()) != null) + result.append(cssLine + "\n"); + } catch (IOException e1) { + logger.log(Level.SEVERE, e1.getLocalizedMessage(), e1); + } + + result.append("
\n"); + +// if(description != null) +// result.append("

" + description + "

\n"); + result.append(stripHtml(htmlContent, false) + "
\n"); + result.append("
\n\n\n"); + + Html html = new Html(); + html.setContent(result.toString()); + content.appendChild(html); + panelEmpty = false; + } + + // Window + int AD_Window_ID = rs.getInt(X_PA_DashboardContent.COLUMNNAME_AD_Window_ID); + if(AD_Window_ID > 0) + { + int AD_Menu_ID = rs.getInt(X_AD_Menu.COLUMNNAME_AD_Menu_ID); + ToolBarButton btn = new ToolBarButton(String.valueOf(AD_Menu_ID)); + MMenu menu = new MMenu(Env.getCtx(), AD_Menu_ID, null); + btn.setLabel(menu.getName()); + btn.addEventListener(Events.ON_CLICK, this); + content.appendChild(btn); + panelEmpty = false; + } + + // Goal + int PA_Goal_ID = rs.getInt(X_PA_DashboardContent.COLUMNNAME_PA_Goal_ID); + if(PA_Goal_ID > 0) + { + StringBuffer result = new StringBuffer(""); + + URL url = getClass().getClassLoader(). + getResource("org/compiere/images/PAPanel.css"); + InputStreamReader ins; + try { + ins = new InputStreamReader(url.openStream()); + BufferedReader bufferedReader = new BufferedReader( ins ); + String cssLine; + while ((cssLine = bufferedReader.readLine()) != null) + result.append(cssLine + "\n"); + } catch (IOException e1) { + logger.log(Level.SEVERE, e1.getLocalizedMessage(), e1); + } + + result.append("
\n"); + result.append(renderGoals(PA_Goal_ID, content)); + result.append("
\n\n\n"); + + Html html = new Html(); + html.setContent(result.toString()); + content.appendChild(html); + panelEmpty = false; + } + + // ZUL file url + String url = rs.getString(X_PA_DashboardContent.COLUMNNAME_ZulFilePath); + if(url != null) + { + try { + Component component = Executions.createComponents(url, content, null); + if(component != null) + { + if (component instanceof DashboardPanel) + { + DashboardPanel dashboardPanel = (DashboardPanel) component; + if (!dashboardPanel.getChildren().isEmpty()) { + content.appendChild(dashboardPanel); + dashboardRunnable.add(dashboardPanel); + panelEmpty = false; + } + } + else + { + content.appendChild(component); + panelEmpty = false; + } + } + } catch (Exception e) { + logger.log(Level.WARNING, "Failed to create components. zul="+url, e); + } + } + + if (panelEmpty) + panel.detach(); + } + } catch(Exception e) { + logger.log(Level.WARNING, "Failed to create dashboard content", e); + } finally { + DB.close(rs, pstmt); + } + // + + //register as 0 + registerWindow(homeTab); + + if (!portalLayout.getDesktop().isServerPushEnabled()) + portalLayout.getDesktop().enableServerPush(true); + + dashboardRunnable.refreshDashboard(); + + dashboardThread = new Thread(dashboardRunnable, "UpdateInfo"); + dashboardThread.setDaemon(true); + dashboardThread.start(); + } + + public void onEvent(Event event) + { + Component comp = event.getTarget(); + String eventName = event.getName(); + + if(eventName.equals(Events.ON_CLICK)) + { + if(comp instanceof ToolBarButton) + { + ToolBarButton btn = (ToolBarButton) comp; + + int menuId = 0; + try + { + menuId = Integer.valueOf(btn.getName()); + } + catch (Exception e) { + + } + + if(menuId > 0) onMenuSelected(menuId); + } + } + } + + public void onServerPush() + { + int noOfNotice = DPActivities.getNoticeCount(); + int noOfRequest = DPActivities.getRequestCount(); + int noOfWorkflow = DPActivities.getWorkflowCount(); + int total = noOfNotice + noOfRequest + noOfWorkflow; + + navigationPanel.setLabel(2, "Activities (" + total + ")"); + navigationPanel.setTooltiptext(2, "Notice : " + noOfNotice + ", Request : " + noOfRequest + ", Workflow Activities : " + noOfWorkflow); + } + + /** + * + * @param page + */ + public void setPage(Page page) { + if (this.page != page) { + layout.setPage(page); + this.page = page; + } + } + + /** + * Get the root component + * @return Component + */ + public Component getComponent() { + return layout; + } + + public void logout() { + if (dashboardThread != null && dashboardThread.isAlive()) { + dashboardRunnable.stop(); + dashboardThread.interrupt(); + } + } +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/TabbedDesktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/TabbedDesktop.java new file mode 100644 index 0000000000..1865ed68b0 --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/TabbedDesktop.java @@ -0,0 +1,285 @@ +/****************************************************************************** + * Copyright (C) 2008 Low Heng Sin * + * Copyright (C) 2008 Idalica Corporation * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ +package org.adempiere.webui.desktop; + +import java.util.List; + +import org.adempiere.webui.apps.ProcessDialog; +import org.adempiere.webui.apps.wf.WFPanel; +import org.adempiere.webui.component.DesktopTabpanel; +import org.adempiere.webui.component.Tabbox; +import org.adempiere.webui.component.Tabpanel; +import org.adempiere.webui.component.Window; +import org.adempiere.webui.panel.ADForm; +import org.adempiere.webui.part.WindowContainer; +import org.adempiere.webui.window.ADWindow; +import org.adempiere.webui.window.WTask; +import org.compiere.model.MQuery; +import org.compiere.model.MTask; +import org.compiere.util.Env; +import org.compiere.util.WebDoc; +import org.zkoss.util.media.AMedia; +import org.zkoss.zk.ui.Component; +import org.zkoss.zul.Iframe; +import org.zkoss.zul.Tab; +import org.zkoss.zul.Tabpanels; + +/** + * A Tabbed MDI implementation + * @author hengsin + * + */ +public abstract class TabbedDesktop extends AbstractDesktop { + + protected WindowContainer windowContainer; + + public TabbedDesktop() { + super(); + windowContainer = new WindowContainer(); + } + + /** + * + * @param processId + * @param soTrx + * @return ProcessDialog + */ + public ProcessDialog openProcessDialog(int processId, boolean soTrx) { + ProcessDialog pd = new ProcessDialog (processId, soTrx); + if (pd.isValid()) { + DesktopTabpanel tabPanel = new DesktopTabpanel(); + pd.setParent(tabPanel); + String title = pd.getTitle(); + pd.setTitle(null); + windowContainer.addWindow(tabPanel, title, true); + } + return pd; + } + + /** + * + * @param formId + * @return ADWindow + */ + public ADForm openForm(int formId) { + ADForm form = ADForm.openForm(formId); + + DesktopTabpanel tabPanel = new DesktopTabpanel(); + form.setParent(tabPanel); + //do not show window title when open as tab + form.setTitle(null); + windowContainer.addWindow(tabPanel, form.getFormName(), true); + + return form; + } + + /** + * + * @param workflow_ID + */ + public void openWorkflow(int workflow_ID) { + WFPanel p = new WFPanel(); + p.load(workflow_ID); + + DesktopTabpanel tabPanel = new DesktopTabpanel(); + p.setParent(tabPanel); + windowContainer.addWindow(tabPanel, p.getWorkflow().getName(), true); + } + + /** + * + * @param windowId + * @return ADWindow + */ + public ADWindow openWindow(int windowId) { + ADWindow adWindow = new ADWindow(Env.getCtx(), windowId); + + DesktopTabpanel tabPanel = new DesktopTabpanel(); + if (adWindow.createPart(tabPanel) != null) { + windowContainer.addWindow(tabPanel, adWindow.getTitle(), true); + return adWindow; + } else { + //user cancel + return null; + } + } + + /** + * + * @param taskId + */ + public void openTask(int taskId) { + MTask task = new MTask(Env.getCtx(), taskId, null); + new WTask(task.getName(), task); + } + + /** + * @param url + */ + public void showURL(String url, boolean closeable) + { + showURL(url, url, closeable); + } + + /** + * + * @param url + * @param title + * @param closeable + */ + public void showURL(String url, String title, boolean closeable) + { + Iframe iframe = new Iframe(url); + addWin(iframe, title, closeable); + } + + /** + * @param webDoc + * @param title + * @param closeable + */ + public void showURL(WebDoc webDoc, String title, boolean closeable) + { + Iframe iframe = new Iframe(); + + AMedia media = new AMedia(title, "html", "text/html", webDoc.toString().getBytes()); + iframe.setContent(media); + + addWin(iframe, title, closeable); + } + + /** + * + * @param fr + * @param title + * @param closeable + */ + private void addWin(Iframe fr, String title, boolean closeable) + { + fr.setWidth("100%"); + fr.setHeight("100%"); + fr.setStyle("padding: 0; margin: 0; border: none; position: absolute"); + Window window = new Window(); + window.setWidth("100%"); + window.setHeight("100%"); + window.setStyle("padding: 0; margin: 0; border: none"); + window.appendChild(fr); + window.setStyle("position: absolute"); + + Tabpanel tabPanel = new Tabpanel(); + window.setParent(tabPanel); + windowContainer.addWindow(tabPanel, title, closeable); + } + + /** + * @param AD_Window_ID + * @param query + */ + public void showZoomWindow(int AD_Window_ID, MQuery query) + { + ADWindow wnd = new ADWindow(Env.getCtx(), AD_Window_ID, query); + + DesktopTabpanel tabPanel = new DesktopTabpanel(); + wnd.createPart(tabPanel); + windowContainer.insertAfter(windowContainer.getSelectedTab(), tabPanel, wnd.getTitle(), true, true); + } + + /** + * + * @param window + */ + protected void showEmbedded(Window window) + { + Tabpanel tabPanel = new Tabpanel(); + window.setParent(tabPanel); + String title = window.getTitle(); + window.setTitle(null); + if (Window.INSERT_NEXT.equals(window.getAttribute(Window.INSERT_POSITION_KEY))) + windowContainer.insertAfter(windowContainer.getSelectedTab(), tabPanel, title, true, true); + else + windowContainer.addWindow(tabPanel, title, true); + } + + /** + * Close active tab + * @return boolean + */ + public boolean closeActiveWindow() + { + if (windowContainer.getSelectedTab() != null) + { + Tabpanel panel = (Tabpanel) windowContainer.getSelectedTab().getLinkedPanel(); + Component component = panel.getFirstChild(); + Object att = component.getAttribute(WINDOWNO_ATTRIBUTE); + + if ( windowContainer.closeActiveWindow() ) + { + if (att != null && (att instanceof Integer)) + { + unregisterWindow((Integer) att); + } + return true; + } + else + { + return false; + } + } + return false; + } + + /** + * @return Component + */ + public Component getActiveWindow() + { + return windowContainer.getSelectedTab().getLinkedPanel().getFirstChild(); + } + + /** + * + * @param windowNo + * @return boolean + */ + public boolean closeWindow(int windowNo) + { + Tabbox tabbox = windowContainer.getComponent(); + Tabpanels panels = tabbox.getTabpanels(); + List childrens = panels.getChildren(); + for (Object child : childrens) + { + Tabpanel panel = (Tabpanel) child; + Component component = panel.getFirstChild(); + Object att = component.getAttribute(WINDOWNO_ATTRIBUTE); + if (att != null && (att instanceof Integer)) + { + if (windowNo == (Integer)att) + { + Tab tab = panel.getLinkedTab(); + panel.getLinkedTab().onClose(); + if (tab.getParent() == null) + { + unregisterWindow(windowNo); + return true; + } + else + { + return false; + } + } + } + } + return false; + } +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/session/SessionManager.java b/zkwebui/WEB-INF/src/org/adempiere/webui/session/SessionManager.java index 6a247aa9a2..d5f33ef19a 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/session/SessionManager.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/session/SessionManager.java @@ -19,8 +19,8 @@ package org.adempiere.webui.session; import java.util.Properties; -import org.adempiere.webui.IDesktop; import org.adempiere.webui.IWebClient; +import org.adempiere.webui.desktop.IDesktop; import org.compiere.util.Env; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Session; diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/window/ADWindow.java b/zkwebui/WEB-INF/src/org/adempiere/webui/window/ADWindow.java index 1c19c37154..785c9b6168 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/window/ADWindow.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/window/ADWindow.java @@ -19,7 +19,7 @@ package org.adempiere.webui.window; import java.util.Properties; -import org.adempiere.webui.Desktop; +import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.panel.ADWindowPanel; import org.adempiere.webui.part.AbstractUIPart; import org.adempiere.webui.session.SessionManager; @@ -77,7 +77,7 @@ public class ADWindow extends AbstractUIPart { windowPanelComponent = windowPanel.createPart(parent); windowPanelComponent.setAttribute("ADWindow", this); - windowPanelComponent.setAttribute(Desktop.WINDOWNO_ATTRIBUTE, windowNo); + windowPanelComponent.setAttribute(IDesktop.WINDOWNO_ATTRIBUTE, windowNo); if (windowPanel.initPanel(adWindowId, query)) { _title = windowPanel.getTitle(); diff --git a/zkwebui/zul/activities.zul b/zkwebui/zul/activities.zul index 22eda91baf..1e2f63ec26 100644 --- a/zkwebui/zul/activities.zul +++ b/zkwebui/zul/activities.zul @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/zkwebui/zul/calendar.zul b/zkwebui/zul/calendar.zul index 4118f73fec..6fcb0c5f88 100644 --- a/zkwebui/zul/calendar.zul +++ b/zkwebui/zul/calendar.zul @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/zkwebui/zul/favourites.zul b/zkwebui/zul/favourites.zul index 4ee81bf1a5..5f069f1ea4 100644 --- a/zkwebui/zul/favourites.zul +++ b/zkwebui/zul/favourites.zul @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/zkwebui/zul/performance.zul b/zkwebui/zul/performance.zul index 52b8f22588..d2ecfb7702 100644 --- a/zkwebui/zul/performance.zul +++ b/zkwebui/zul/performance.zul @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/zkwebui/zul/views.zul b/zkwebui/zul/views.zul index 0cb859fe68..e24627e849 100644 --- a/zkwebui/zul/views.zul +++ b/zkwebui/zul/views.zul @@ -1,2 +1,2 @@ - \ No newline at end of file + \ No newline at end of file