IDEMPIERE-1379:Info Windows should have their own icon/image
move manage imageCache to ManageImageCache improve imageCache for + don't load local image to cache + handle exception when wrong link or disconnect network + when many MImage has same extenal url, just load one time + tab for "info window" has same icon when display in daskboad view
This commit is contained in:
parent
e99cff2f02
commit
517f0299e1
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package org.adempiere.webui.adwindow;
|
package org.adempiere.webui.adwindow;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -35,9 +34,7 @@ import org.compiere.model.MToolBarButton;
|
||||||
import org.compiere.model.MToolBarButtonRestrict;
|
import org.compiere.model.MToolBarButtonRestrict;
|
||||||
import org.compiere.model.MWindow;
|
import org.compiere.model.MWindow;
|
||||||
import org.compiere.model.X_AD_ToolBarButton;
|
import org.compiere.model.X_AD_ToolBarButton;
|
||||||
import org.compiere.util.CCache;
|
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
import org.zkoss.image.AImage;
|
|
||||||
import org.zkoss.zk.ui.Component;
|
import org.zkoss.zk.ui.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,8 +57,6 @@ public class ADWindow extends AbstractUIPart
|
||||||
private Component windowPanelComponent;
|
private Component windowPanelComponent;
|
||||||
private MImage image;
|
private MImage image;
|
||||||
|
|
||||||
private static final CCache<Integer, AImage> imageCache = new CCache<Integer, AImage>(null, "WindowImageCache", 5, false);
|
|
||||||
|
|
||||||
private Map<Integer, List<String>> tabToolbarRestricMap = new HashMap<Integer, List<String>>();
|
private Map<Integer, List<String>> tabToolbarRestricMap = new HashMap<Integer, List<String>>();
|
||||||
|
|
||||||
private List<String> windowToolbarRestrictList = null;
|
private List<String> windowToolbarRestrictList = null;
|
||||||
|
@ -129,23 +124,6 @@ public class ADWindow extends AbstractUIPart
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AImage getAImage() throws IOException {
|
|
||||||
MImage image = getMImage();
|
|
||||||
AImage aImage = null;
|
|
||||||
if (image != null) {
|
|
||||||
synchronized (imageCache) {
|
|
||||||
aImage = imageCache.get(image.getAD_Image_ID());
|
|
||||||
}
|
|
||||||
if (aImage == null) {
|
|
||||||
aImage = new AImage(image.getName(), image.getData());
|
|
||||||
synchronized (imageCache) {
|
|
||||||
imageCache.put(image.getAD_Image_ID(), aImage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return aImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Component doCreatePart(Component parent)
|
protected Component doCreatePart(Component parent)
|
||||||
{
|
{
|
||||||
windowPanelComponent = windowContent.createPart(parent);
|
windowPanelComponent = windowContent.createPart(parent);
|
||||||
|
|
|
@ -17,6 +17,13 @@
|
||||||
|
|
||||||
package org.adempiere.webui.component;
|
package org.adempiere.webui.component;
|
||||||
|
|
||||||
|
import org.adempiere.webui.adwindow.ADWindow;
|
||||||
|
import org.adempiere.webui.util.ManageImageCache;
|
||||||
|
import org.compiere.model.MImage;
|
||||||
|
import org.compiere.model.MInfoWindow;
|
||||||
|
import org.zkoss.image.Image;
|
||||||
|
import org.zkoss.zul.impl.LabelImageElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:agramdass@gmail.com">Ashley G Ramdass</a>
|
* @author <a href="mailto:agramdass@gmail.com">Ashley G Ramdass</a>
|
||||||
|
@ -38,6 +45,11 @@ public class Tab extends org.zkoss.zul.Tab
|
||||||
public Tab()
|
public Tab()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDecorateInfo (DecorateInfo decorateInfo){
|
||||||
|
if (decorateInfo != null)
|
||||||
|
decorateInfo.decorate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,4 +60,50 @@ public class Tab extends org.zkoss.zul.Tab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class contain decorate info
|
||||||
|
* at the moment, has only image info
|
||||||
|
* at the moment, it's use to transfer decorate info from info window, standard window, report, process,... to tab
|
||||||
|
* @author hieplq
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static class DecorateInfo {
|
||||||
|
private String imageKey;
|
||||||
|
private String imageIntenalUrl;
|
||||||
|
|
||||||
|
public void decorate (LabelImageElement comp){
|
||||||
|
if (imageIntenalUrl != null)
|
||||||
|
comp.setImage(imageIntenalUrl);
|
||||||
|
else if (imageKey != null){
|
||||||
|
Image ico = ManageImageCache.instance().getImage(imageKey);
|
||||||
|
if (ico != null)
|
||||||
|
comp.setImageContent(ico);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecorateInfo (MImage imageData){
|
||||||
|
imageIntenalUrl = ManageImageCache.getImageInternalUrl(imageData);
|
||||||
|
if (imageIntenalUrl == null)
|
||||||
|
imageKey = ManageImageCache.instance().loadImage(imageData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecorateInfo (String imagePath){
|
||||||
|
imageIntenalUrl = ManageImageCache.getImageInternalUrl(imagePath);
|
||||||
|
if (imageIntenalUrl == null)
|
||||||
|
imageKey = imagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for create decorate info from adWindow info
|
||||||
|
* @param adWindow
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static DecorateInfo get (ADWindow adWindow){
|
||||||
|
return adWindow == null?null:new DecorateInfo(adWindow.getMImage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DecorateInfo get (MInfoWindow mInfo){
|
||||||
|
return mInfo==null?null:new DecorateInfo(mInfo.getImageURL());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,7 +243,7 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
|
||||||
windowContainer.createPart(windowArea);
|
windowContainer.createPart(windowArea);
|
||||||
|
|
||||||
homeTab = new Tabpanel();
|
homeTab = new Tabpanel();
|
||||||
windowContainer.addWindow(homeTab, Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Home")), false);
|
windowContainer.addWindow(homeTab, Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Home")), false, null);
|
||||||
homeTab.getLinkedTab().setSclass("desktop-hometab");
|
homeTab.getLinkedTab().setSclass("desktop-hometab");
|
||||||
homeTab.setSclass("desktop-home-tabpanel");
|
homeTab.setSclass("desktop-home-tabpanel");
|
||||||
BusyDialog busyDialog = new BusyDialog();
|
BusyDialog busyDialog = new BusyDialog();
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package org.adempiere.webui.desktop;
|
package org.adempiere.webui.desktop;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.adempiere.util.Callback;
|
import org.adempiere.util.Callback;
|
||||||
|
@ -22,6 +21,7 @@ import org.adempiere.webui.adwindow.ADWindow;
|
||||||
import org.adempiere.webui.apps.ProcessDialog;
|
import org.adempiere.webui.apps.ProcessDialog;
|
||||||
import org.adempiere.webui.apps.wf.WFPanel;
|
import org.adempiere.webui.apps.wf.WFPanel;
|
||||||
import org.adempiere.webui.component.DesktopTabpanel;
|
import org.adempiere.webui.component.DesktopTabpanel;
|
||||||
|
import org.adempiere.webui.component.Tab.DecorateInfo;
|
||||||
import org.adempiere.webui.component.Tabbox;
|
import org.adempiere.webui.component.Tabbox;
|
||||||
import org.adempiere.webui.component.Tabpanel;
|
import org.adempiere.webui.component.Tabpanel;
|
||||||
import org.adempiere.webui.component.Window;
|
import org.adempiere.webui.component.Window;
|
||||||
|
@ -32,11 +32,11 @@ import org.adempiere.webui.panel.InfoPanel;
|
||||||
import org.adempiere.webui.part.WindowContainer;
|
import org.adempiere.webui.part.WindowContainer;
|
||||||
import org.adempiere.webui.window.FDialog;
|
import org.adempiere.webui.window.FDialog;
|
||||||
import org.adempiere.webui.window.WTask;
|
import org.adempiere.webui.window.WTask;
|
||||||
|
import org.compiere.model.MInfoWindow;
|
||||||
import org.compiere.model.MQuery;
|
import org.compiere.model.MQuery;
|
||||||
import org.compiere.model.MTask;
|
import org.compiere.model.MTask;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
import org.compiere.wf.MWorkflow;
|
import org.compiere.wf.MWorkflow;
|
||||||
import org.zkoss.image.AImage;
|
|
||||||
import org.zkoss.util.media.AMedia;
|
import org.zkoss.util.media.AMedia;
|
||||||
import org.zkoss.zk.ui.Component;
|
import org.zkoss.zk.ui.Component;
|
||||||
import org.zkoss.zk.ui.event.Event;
|
import org.zkoss.zk.ui.event.Event;
|
||||||
|
@ -73,7 +73,7 @@ public abstract class TabbedDesktop extends AbstractDesktop {
|
||||||
String title = pd.getTitle();
|
String title = pd.getTitle();
|
||||||
pd.setTitle(null);
|
pd.setTitle(null);
|
||||||
preOpenNewTab();
|
preOpenNewTab();
|
||||||
windowContainer.addWindow(tabPanel, title, true);
|
windowContainer.addWindow(tabPanel, title, true, null);
|
||||||
Events.postEvent(ProcessDialog.ON_INITIAL_FOCUS_EVENT, pd, null);
|
Events.postEvent(ProcessDialog.ON_INITIAL_FOCUS_EVENT, pd, null);
|
||||||
}
|
}
|
||||||
return pd;
|
return pd;
|
||||||
|
@ -93,7 +93,7 @@ public abstract class TabbedDesktop extends AbstractDesktop {
|
||||||
//do not show window title when open as tab
|
//do not show window title when open as tab
|
||||||
form.setTitle(null);
|
form.setTitle(null);
|
||||||
preOpenNewTab();
|
preOpenNewTab();
|
||||||
windowContainer.addWindow(tabPanel, form.getFormName(), true);
|
windowContainer.addWindow(tabPanel, form.getFormName(), true, null);
|
||||||
form.focus();
|
form.focus();
|
||||||
} else {
|
} else {
|
||||||
form.setAttribute(Window.MODE_KEY, form.getWindowMode());
|
form.setAttribute(Window.MODE_KEY, form.getWindowMode());
|
||||||
|
@ -117,7 +117,7 @@ public abstract class TabbedDesktop extends AbstractDesktop {
|
||||||
String title = infoPanel.getTitle();
|
String title = infoPanel.getTitle();
|
||||||
infoPanel.setTitle(null);
|
infoPanel.setTitle(null);
|
||||||
preOpenNewTab();
|
preOpenNewTab();
|
||||||
windowContainer.addWindow(tabPanel, title, true);
|
windowContainer.addWindow(tabPanel, title, true, DecorateInfo.get(MInfoWindow.get(infoId, null)));
|
||||||
infoPanel.focus();
|
infoPanel.focus();
|
||||||
} else {
|
} else {
|
||||||
FDialog.error(0, "NotValid");
|
FDialog.error(0, "NotValid");
|
||||||
|
@ -135,7 +135,7 @@ public abstract class TabbedDesktop extends AbstractDesktop {
|
||||||
DesktopTabpanel tabPanel = new DesktopTabpanel();
|
DesktopTabpanel tabPanel = new DesktopTabpanel();
|
||||||
p.setParent(tabPanel);
|
p.setParent(tabPanel);
|
||||||
preOpenNewTab();
|
preOpenNewTab();
|
||||||
windowContainer.addWindow(tabPanel, p.getWorkflow().get_Translation(MWorkflow.COLUMNNAME_Name), true);
|
windowContainer.addWindow(tabPanel, p.getWorkflow().get_Translation(MWorkflow.COLUMNNAME_Name), true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,7 +160,8 @@ public abstract class TabbedDesktop extends AbstractDesktop {
|
||||||
final DesktopTabpanel tabPanel = new DesktopTabpanel();
|
final DesktopTabpanel tabPanel = new DesktopTabpanel();
|
||||||
String id = AdempiereIdGenerator.escapeId(adWindow.getTitle());
|
String id = AdempiereIdGenerator.escapeId(adWindow.getTitle());
|
||||||
tabPanel.setId(id+"_"+adWindow.getADWindowContent().getWindowNo());
|
tabPanel.setId(id+"_"+adWindow.getADWindowContent().getWindowNo());
|
||||||
final Tab tab = windowContainer.addWindow(tabPanel, adWindow.getTitle(), true);
|
final Tab tab = windowContainer.addWindow(tabPanel, adWindow.getTitle(), true, DecorateInfo.get(adWindow));
|
||||||
|
|
||||||
tab.setClosable(false);
|
tab.setClosable(false);
|
||||||
final OpenWindowRunnable runnable = new OpenWindowRunnable(adWindow, tab, tabPanel, callback);
|
final OpenWindowRunnable runnable = new OpenWindowRunnable(adWindow, tab, tabPanel, callback);
|
||||||
preOpenNewTab();
|
preOpenNewTab();
|
||||||
|
@ -233,7 +234,7 @@ public abstract class TabbedDesktop extends AbstractDesktop {
|
||||||
Tabpanel tabPanel = new Tabpanel();
|
Tabpanel tabPanel = new Tabpanel();
|
||||||
window.setParent(tabPanel);
|
window.setParent(tabPanel);
|
||||||
preOpenNewTab();
|
preOpenNewTab();
|
||||||
windowContainer.addWindow(tabPanel, title, closeable);
|
windowContainer.addWindow(tabPanel, title, closeable, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -245,7 +246,7 @@ public abstract class TabbedDesktop extends AbstractDesktop {
|
||||||
final ADWindow wnd = new ADWindow(Env.getCtx(), AD_Window_ID, query);
|
final ADWindow wnd = new ADWindow(Env.getCtx(), AD_Window_ID, query);
|
||||||
|
|
||||||
final DesktopTabpanel tabPanel = new DesktopTabpanel();
|
final DesktopTabpanel tabPanel = new DesktopTabpanel();
|
||||||
final Tab tab = windowContainer.insertAfter(windowContainer.getSelectedTab(), tabPanel, wnd.getTitle(), true, true);
|
final Tab tab = windowContainer.insertAfter(windowContainer.getSelectedTab(), tabPanel, wnd.getTitle(), true, true, DecorateInfo.get(wnd));
|
||||||
tab.setClosable(false);
|
tab.setClosable(false);
|
||||||
final OpenWindowRunnable runnable = new OpenWindowRunnable(wnd, tab, tabPanel, null);
|
final OpenWindowRunnable runnable = new OpenWindowRunnable(wnd, tab, tabPanel, null);
|
||||||
preOpenNewTab();
|
preOpenNewTab();
|
||||||
|
@ -277,9 +278,9 @@ public abstract class TabbedDesktop extends AbstractDesktop {
|
||||||
window.setTitle(null);
|
window.setTitle(null);
|
||||||
preOpenNewTab();
|
preOpenNewTab();
|
||||||
if (Window.INSERT_NEXT.equals(window.getAttribute(Window.INSERT_POSITION_KEY)))
|
if (Window.INSERT_NEXT.equals(window.getAttribute(Window.INSERT_POSITION_KEY)))
|
||||||
windowContainer.insertAfter(windowContainer.getSelectedTab(), tabPanel, title, true, true);
|
windowContainer.insertAfter(windowContainer.getSelectedTab(), tabPanel, title, true, true, null);
|
||||||
else
|
else
|
||||||
windowContainer.addWindow(tabPanel, title, true);
|
windowContainer.addWindow(tabPanel, title, true, null);
|
||||||
if (window instanceof IHelpContext)
|
if (window instanceof IHelpContext)
|
||||||
Events.sendEvent(new Event(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT, window));
|
Events.sendEvent(new Event(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT, window));
|
||||||
}
|
}
|
||||||
|
@ -381,13 +382,6 @@ public abstract class TabbedDesktop extends AbstractDesktop {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (adWindow.createPart(tabPanel) != null ) {
|
if (adWindow.createPart(tabPanel) != null ) {
|
||||||
tab.setClosable(true);
|
tab.setClosable(true);
|
||||||
if (adWindow.getMImage() != null) {
|
|
||||||
try {
|
|
||||||
AImage aImage = adWindow.getAImage();
|
|
||||||
tab.setImageContent(aImage);
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.onCallback(adWindow);
|
callback.onCallback(adWindow);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.adempiere.webui.component.Menupopup;
|
import org.adempiere.webui.component.Menupopup;
|
||||||
import org.adempiere.webui.component.Tab;
|
import org.adempiere.webui.component.Tab;
|
||||||
|
import org.adempiere.webui.component.Tab.DecorateInfo;
|
||||||
import org.adempiere.webui.component.Tabbox;
|
import org.adempiere.webui.component.Tabbox;
|
||||||
import org.adempiere.webui.component.Tabpanel;
|
import org.adempiere.webui.component.Tabpanel;
|
||||||
import org.adempiere.webui.component.Tabpanels;
|
import org.adempiere.webui.component.Tabpanels;
|
||||||
|
@ -101,15 +102,63 @@ public class WindowContainer extends AbstractUIPart
|
||||||
return tabbox;
|
return tabbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated keep for compatible, replace by {@link #addWindow(Component, String, boolean, DecorateInfo)}
|
||||||
|
* @param comp
|
||||||
|
* @param title
|
||||||
|
* @param closeable
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Tab addWindow(Component comp, String title, boolean closeable){
|
||||||
|
return addWindow(comp, title, closeable, true, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated keep for compatible, replace by {@link #addWindow(Component, String, boolean, boolean, DecorateInfo)}
|
||||||
|
* @param comp
|
||||||
|
* @param title
|
||||||
|
* @param closeable
|
||||||
|
* @param enable
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Tab addWindow(Component comp, String title, boolean closeable, boolean enable) {
|
||||||
|
return addWindow(comp, title, closeable, true, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated keep for compatible, replace by {@link #insertBefore(Tab, Component, String, boolean, boolean, DecorateInfo)}
|
||||||
|
* @param refTab
|
||||||
|
* @param comp
|
||||||
|
* @param title
|
||||||
|
* @param closeable
|
||||||
|
* @param enable
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Tab insertBefore(Tab refTab, Component comp, String title, boolean closeable, boolean enable){
|
||||||
|
return insertBefore(refTab, comp, title, closeable, enable, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated keep for compatible, replace by {@link #insertAfter(Component, String, boolean, boolean, DecorateInfo)}
|
||||||
|
* @param refTab
|
||||||
|
* @param comp
|
||||||
|
* @param title
|
||||||
|
* @param closeable
|
||||||
|
* @param enable
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Tab insertAfter(Tab refTab, Component comp, String title, boolean closeable, boolean enable){
|
||||||
|
return insertAfter(refTab, comp, title, closeable, enable, null);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param comp
|
* @param comp
|
||||||
* @param title
|
* @param title
|
||||||
* @param closeable
|
* @param closeable
|
||||||
*/
|
*/
|
||||||
public Tab addWindow(Component comp, String title, boolean closeable)
|
public Tab addWindow(Component comp, String title, boolean closeable, DecorateInfo decorateInfo)
|
||||||
{
|
{
|
||||||
return addWindow(comp, title, closeable, true);
|
return addWindow(comp, title, closeable, true, decorateInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,9 +168,9 @@ public class WindowContainer extends AbstractUIPart
|
||||||
* @param closeable
|
* @param closeable
|
||||||
* @param enable
|
* @param enable
|
||||||
*/
|
*/
|
||||||
public Tab addWindow(Component comp, String title, boolean closeable, boolean enable)
|
public Tab addWindow(Component comp, String title, boolean closeable, boolean enable, DecorateInfo decorateInfo)
|
||||||
{
|
{
|
||||||
return insertBefore(null, comp, title, closeable, enable);
|
return insertBefore(null, comp, title, closeable, enable, decorateInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -132,9 +181,10 @@ public class WindowContainer extends AbstractUIPart
|
||||||
* @param closeable
|
* @param closeable
|
||||||
* @param enable
|
* @param enable
|
||||||
*/
|
*/
|
||||||
public Tab insertBefore(Tab refTab, Component comp, String title, boolean closeable, boolean enable)
|
public Tab insertBefore(Tab refTab, Component comp, String title, boolean closeable, boolean enable, DecorateInfo decorateInfo)
|
||||||
{
|
{
|
||||||
final Tab tab = new Tab();
|
final Tab tab = new Tab();
|
||||||
|
tab.setDecorateInfo(decorateInfo);
|
||||||
if (title != null)
|
if (title != null)
|
||||||
{
|
{
|
||||||
setTabTitle(title, tab);
|
setTabTitle(title, tab);
|
||||||
|
@ -318,12 +368,12 @@ public class WindowContainer extends AbstractUIPart
|
||||||
* @param closeable
|
* @param closeable
|
||||||
* @param enable
|
* @param enable
|
||||||
*/
|
*/
|
||||||
public Tab insertAfter(Tab refTab, Component comp, String title, boolean closeable, boolean enable)
|
public Tab insertAfter(Tab refTab, Component comp, String title, boolean closeable, boolean enable, DecorateInfo decorateInfo)
|
||||||
{
|
{
|
||||||
if (refTab == null)
|
if (refTab == null)
|
||||||
return addWindow(comp, title, closeable, enable);
|
return addWindow(comp, title, closeable, enable, decorateInfo);
|
||||||
else
|
else
|
||||||
return insertBefore((Tab)refTab.getNextSibling(), comp, title, closeable, enable);
|
return insertBefore((Tab)refTab.getNextSibling(), comp, title, closeable, enable, decorateInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,223 @@
|
||||||
|
/**********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
package org.adempiere.webui.util;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.base.Core;
|
||||||
|
import org.compiere.model.MImage;
|
||||||
|
import org.compiere.util.CCache;
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.compiere.util.Env;
|
||||||
|
import org.zkoss.image.AImage;
|
||||||
|
import org.zkoss.image.Image;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normal image can come from inside system or from outside system.
|
||||||
|
* with image from outside for performance we will cache it.
|
||||||
|
* this class for manage image cache and provide help function relate
|
||||||
|
* @author hieplq
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ManageImageCache {
|
||||||
|
|
||||||
|
protected static transient CLogger log = CLogger.getCLogger (ManageImageCache.class);
|
||||||
|
/**
|
||||||
|
* this cache is don't expire, if must restart cache when has update image.
|
||||||
|
* better use a timer, example reset cache after 10 minute has update. it help user can change a batch of image and reset one time.
|
||||||
|
*/
|
||||||
|
private final CCache<String, Image> imageCache = new CCache<String, Image>(null, "WindowImageCache", 50, 0, false);
|
||||||
|
|
||||||
|
private static ManageImageCache instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get instance
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ManageImageCache instance(){
|
||||||
|
if (instance == null){
|
||||||
|
synchronized (ManageImageCache.class){
|
||||||
|
if (instance == null)
|
||||||
|
instance = new ManageImageCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* investigate image path of MImage, if path is a internal return internal url other return null
|
||||||
|
* @param image
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getImageInternalUrl (MImage image){
|
||||||
|
if (image == null)
|
||||||
|
return null;
|
||||||
|
return getImageInternalUrl(image.getImageURL());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* investigate image path, if path is a internal return internal url other return null
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getImageInternalUrl (String url){
|
||||||
|
if (url == null || url.trim().length() == 0 || url.indexOf("://") > 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
URL urlRsource = Core.getResourceFinder().getResource(url);
|
||||||
|
return urlRsource == null?null:urlRsource.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load image from url
|
||||||
|
* @param imagePath
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected static byte [] loadImageData (String imagePath){
|
||||||
|
byte [] data = null;
|
||||||
|
|
||||||
|
URLConnection conn;
|
||||||
|
try {
|
||||||
|
URL url = new URL(imagePath);
|
||||||
|
conn = url.openConnection();
|
||||||
|
|
||||||
|
conn.setUseCaches(false);
|
||||||
|
InputStream is = conn.getInputStream();
|
||||||
|
byte[] buffer = new byte[1024*8]; // 8kB
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
int length = -1;
|
||||||
|
while ((length = is.read(buffer)) != -1)
|
||||||
|
os.write(buffer, 0, length);
|
||||||
|
is.close();
|
||||||
|
data = os.toByteArray();
|
||||||
|
os.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (log.isLoggable(Level.CONFIG)) log.config (e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if image is don't in cache, load it (imagePath can id of MImage)
|
||||||
|
* @param imagePath
|
||||||
|
* @return image load from path. null when has any exception
|
||||||
|
*/
|
||||||
|
public Image getImage(String imagePath){
|
||||||
|
if (imagePath == null || imagePath.trim().length() == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Image aImage = null;
|
||||||
|
boolean hasCache = false;
|
||||||
|
synchronized (imageCache) {
|
||||||
|
hasCache = imageCache.containsKey(imagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasCache) {
|
||||||
|
try{
|
||||||
|
int mImageId = Integer.parseInt(imagePath);
|
||||||
|
loadImage(MImage.get(Env.getCtx(), mImageId));
|
||||||
|
}catch (NumberFormatException ex){
|
||||||
|
loadExtend(imagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (imageCache) {
|
||||||
|
aImage = imageCache.get(imagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return aImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if MImage contain extend image or binary image data, load it into cache and return key
|
||||||
|
* other return null
|
||||||
|
* @param mImage
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String loadImage (MImage mImage){
|
||||||
|
if (mImage == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
boolean hasCache = false;
|
||||||
|
String strId = String.valueOf(mImage.get_ID());
|
||||||
|
synchronized (imageCache) {
|
||||||
|
hasCache = imageCache.containsKey(strId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hasCache){
|
||||||
|
return strId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mImage.getBinaryData() != null){
|
||||||
|
synchronized (imageCache) {
|
||||||
|
Image loadImage = null;
|
||||||
|
try {
|
||||||
|
loadImage = new AImage (mImage.getName(), mImage.getBinaryData());
|
||||||
|
} catch (IOException e) {
|
||||||
|
// do nothing treat image as null
|
||||||
|
}
|
||||||
|
imageCache.put(String.valueOf(mImage.get_ID()), loadImage);
|
||||||
|
}
|
||||||
|
return strId;
|
||||||
|
}else if (mImage.getImageURL() != null && mImage.getImageURL().trim().length() > 0 && getImageInternalUrl(mImage.getImageURL()) == null){
|
||||||
|
synchronized (imageCache) {
|
||||||
|
hasCache = imageCache.containsKey(mImage.getImageURL());
|
||||||
|
}
|
||||||
|
if (!hasCache){
|
||||||
|
loadExtend (mImage.getImageURL());
|
||||||
|
}
|
||||||
|
return mImage.getImageURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load extend image into cache
|
||||||
|
* @param imagePath
|
||||||
|
*/
|
||||||
|
protected void loadExtend (String imagePath){
|
||||||
|
byte[] data = loadImageData(imagePath);
|
||||||
|
AImage aImage = null;
|
||||||
|
// when can't load image (by incorrect url or disconnect or any exception, just set image as null
|
||||||
|
if (data != null)
|
||||||
|
try {
|
||||||
|
aImage = new AImage(imagePath, data);
|
||||||
|
} catch (IOException e) {
|
||||||
|
aImage = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (imageCache) {
|
||||||
|
imageCache.put(imagePath, aImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ package org.adempiere.webui.util;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.adempiere.base.IResourceFinder;
|
import org.adempiere.base.IResourceFinder;
|
||||||
import org.adempiere.webui.WebUIActivator;
|
import org.adempiere.webui.WebUIActivator;
|
||||||
|
@ -40,6 +41,7 @@ public class WebUIResourceFinder implements IResourceFinder {
|
||||||
return WebUIActivator.getBundleContext().getBundle().findEntries(path, pattern, false);
|
return WebUIActivator.getBundleContext().getBundle().findEntries(path, pattern, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Pattern patternOnlyName = Pattern.compile("\\w+\\.\\w+");
|
||||||
@Override
|
@Override
|
||||||
public URL getResource(String name) {
|
public URL getResource(String name) {
|
||||||
if ("images/iDempiereHR.png".equals(name) || "images/iDempiere.png".equals(name)) {
|
if ("images/iDempiereHR.png".equals(name) || "images/iDempiere.png".equals(name)) {
|
||||||
|
@ -47,6 +49,9 @@ public class WebUIResourceFinder implements IResourceFinder {
|
||||||
}
|
}
|
||||||
Enumeration<URL> e = find(name);
|
Enumeration<URL> e = find(name);
|
||||||
URL url = e != null && e.hasMoreElements() ? e.nextElement() : null;
|
URL url = e != null && e.hasMoreElements() ? e.nextElement() : null;
|
||||||
|
if (url == null && patternOnlyName.matcher(name).matches()){
|
||||||
|
name = "images/" + name;
|
||||||
|
}
|
||||||
if (url == null && name.startsWith("org/compiere/images")) {
|
if (url == null && name.startsWith("org/compiere/images")) {
|
||||||
String t = name.substring("org/compiere/".length());
|
String t = name.substring("org/compiere/".length());
|
||||||
t = ThemeManager.getThemeResource(t);
|
t = ThemeManager.getThemeResource(t);
|
||||||
|
|
Loading…
Reference in New Issue