package com.aelitis.azureus.ui.swt.views.skin;
import java.util.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.ui.swt.Utils;
import com.aelitis.azureus.ui.UIFunctionsUserPrompter;
import com.aelitis.azureus.ui.UserPrompterResultListener;
import com.aelitis.azureus.ui.swt.skin.*;
import com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog.SkinnedDialogClosedListener;
public class VuzeMessageBox
implements UIFunctionsUserPrompter, SkinnedDialogClosedListener
{
private static final int BUTTON_PADDING = 2;
private static final int MIN_BUTTON_WIDTH = 50;
private String title;
private String text;
private String[] buttonIDs;
private Integer[] buttonVals;
private Button def_button;
private int defaultButtonPos;
private int result = -1;
private ArrayList<UserPrompterResultListener> resultListeners = new ArrayList<UserPrompterResultListener>(1);
private VuzeMessageBoxListener vuzeMessageBoxListener;
private SWTSkinObjectContainer soExtra;
private SkinnedDialog dlg;
private String iconResource;
private String subtitle;
private java.util.List<rbInfo> listRBs = new ArrayList<rbInfo>();
private SWTSkin skin;
private String textIconResource;
private boolean closed;
private boolean opened;
private Button[] buttons;
private Map<Integer, Boolean> buttonsEnabled = new HashMap<Integer, Boolean>();
public VuzeMessageBox(final String title, final String text,
final String[] buttons, final int defaultOption) {
this.title = title;
this.text = text;
this.buttonIDs = buttons == null ? new String[0] : buttons;
this.defaultButtonPos = defaultOption;
}
public void setButtonEnabled(final int buttonVal, final boolean enable) {
buttonsEnabled.put(buttonVal, enable);
if (buttons == null) {
return;
}
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (buttons == null) {
return;
}
int pos = getButtonPosFromVal(buttonVal);
if (pos >= 0 && pos < buttons.length) {
Button button = buttons[pos];
if (button != null && !button.isDisposed()) {
button.setEnabled(enable);
}
}
}
});
}
public void setButtonVals(Integer[] buttonVals) {
this.buttonVals = buttonVals;
int cancelPos = -1;
for (int i = 0; i < buttonVals.length; i++) {
Integer val = buttonVals[i];
if (val == SWT.CANCEL) {
cancelPos = i;
break;
}
}
if (cancelPos >= 0) {
if (Constants.isOSX && cancelPos != 0) {
String cancelButton = buttonIDs[cancelPos];
for (int i = cancelPos; i > 0; i--) {
if (defaultButtonPos == i) {
defaultButtonPos = i - 1;
}
this.buttonIDs[i] = this.buttonIDs[i - 1];
this.buttonVals[i] = this.buttonVals[i - 1];
}
if (defaultButtonPos == 0) {
defaultButtonPos = 1;
}
buttonIDs[0] = cancelButton;
buttonVals[0] = SWT.CANCEL;
} // else if (cancelPos != buttons.length - 1) { // TODO: move to end
}
}
private int getButtonVal(int buttonPos) {
if (buttonVals == null) {
return buttonPos;
}
if (buttonPos < 0 || buttonPos >= buttonVals.length) {
return SWT.CANCEL;
}
return buttonVals[buttonPos].intValue();
}
public void setSubTitle(String s) {
subtitle = s;
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#getAutoCloseInMS()
*/
public int getAutoCloseInMS() {
return 0;
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#getHtml()
*/
public String getHtml() {
return null;
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#getRememberID()
*/
public String getRememberID() {
return null;
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#getRememberText()
*/
public String getRememberText() {
return null;
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#isAutoClosed()
*/
public boolean isAutoClosed() {
return false;
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#open(com.aelitis.azureus.ui.UserPrompterResultListener)
*/
public void open(final UserPrompterResultListener l) {
opened = true;
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
// catch someone calling close() while we are opening
if (closed) {
return;
}
synchronized (VuzeMessageBox.this) {
_open(l);
}
}
});
}
protected void _open(UserPrompterResultListener l) {
if (l != null) {
synchronized (resultListeners) {
resultListeners.add(l);
}
}
dlg = new SkinnedDialog("skin3_dlg_generic", "shell", SWT.DIALOG_TRIM) {
protected void setSkin(SWTSkin skin) {
super.setSkin(skin);
//skin.DEBUGLAYOUT = true;
VuzeMessageBox.this.skin = skin;
synchronized (listRBs) {
for (rbInfo rb : listRBs) {
addResourceBundle(rb.cla, rb.path, rb.name);
}
listRBs.clear();
}
}
public void open() {
super.open();
// need to defer setting the default button to here as otherwise it doesn't
// work (on windows at least...)
if( def_button != null ){
def_button.getShell().setDefaultButton(def_button);
}
}
};
dlg.setTitle(title);
dlg.addCloseListener(this);
SWTSkinObjectText soTopTitle = (SWTSkinObjectText) skin.getSkinObject("top-title");
if (soTopTitle != null) {
soTopTitle.setText(subtitle == null ? title : subtitle);
}
SWTSkinObjectText soText = (SWTSkinObjectText) skin.getSkinObject("middle-title");
if (soText != null) {
soText.setText(text);
}
if (iconResource != null) {
SWTSkinObjectImage soTopLogo = (SWTSkinObjectImage) dlg.getSkin().getSkinObject("top-logo");
if (soTopLogo != null) {
soTopLogo.setImageByID(iconResource, null);
}
}
if (textIconResource != null) {
SWTSkinObjectImage soIcon = (SWTSkinObjectImage) dlg.getSkin().getSkinObject("text-icon");
if (soIcon != null) {
soIcon.setImageByID(textIconResource, null);
}
}
SWTSkinObjectContainer soBottomArea = (SWTSkinObjectContainer) skin.getSkinObject("bottom-area");
if (soBottomArea != null) {
if (buttonIDs.length == 0) {
soBottomArea.setVisible(false);
} else {
createButtons(soBottomArea);
}
}
if (vuzeMessageBoxListener != null) {
soExtra = (SWTSkinObjectContainer) skin.getSkinObject("middle-extra");
try {
vuzeMessageBoxListener.shellReady(dlg.getShell(), soExtra);
} catch (Exception e) {
Debug.out(e);
}
}
if (closed) {
return;
}
dlg.open();
}
private void createButtons(SWTSkinObjectContainer soBottomArea) {
FormData fd;
Composite cBottomArea = soBottomArea.getComposite();
Composite cCenterH = new Composite(cBottomArea, SWT.NONE);
fd = new FormData();
fd.height = 1;
fd.width = 1;
fd.left = new FormAttachment(0);
fd.right = new FormAttachment(100);
cCenterH.setLayoutData(fd);
Composite cCenterV = new Composite(cBottomArea, SWT.NONE);
fd = new FormData();
fd.width = 1;
fd.height = 1;
fd.top = new FormAttachment(0);
fd.bottom = new FormAttachment(100);
cCenterV.setLayoutData(fd);
Composite cButtonArea = new Composite(cBottomArea, SWT.NONE);
// Fix button BG not right on Win7
cButtonArea.setBackgroundMode(SWT.INHERIT_FORCE);
fd = new FormData();
fd.top = new FormAttachment(cCenterV, 0, SWT.CENTER);
fd.left = new FormAttachment(cCenterH, 0, SWT.CENTER);
cButtonArea.setLayoutData(fd);
RowLayout rowLayout = new RowLayout(SWT.HORIZONTAL);
rowLayout.center = true;
rowLayout.spacing = 8;
rowLayout.pack = false;
cButtonArea.setLayout(rowLayout);
buttons = new Button[buttonIDs.length];
for (int i = 0; i < buttonIDs.length; i++) {
String buttonText = buttonIDs[i];
if (buttonText == null) {
continue;
}
Button button = buttons[i] = new Button(cButtonArea, SWT.PUSH);
int buttonVal = buttonVals == null || i >= buttonVals.length ? i : buttonVals[i];
Boolean b = buttonsEnabled.get(buttonVal);
if (b == null) {
b = Boolean.TRUE;
}
button.setEnabled(b);
button.setText(buttonText);
RowData rowData = new RowData();
Point size = button.computeSize(SWT.DEFAULT, SWT.DEFAULT);
size.x += BUTTON_PADDING;
if (size.x < MIN_BUTTON_WIDTH) {
size.x = MIN_BUTTON_WIDTH;
}
rowData.width = size.x;
button.setLayoutData(rowData);
if (defaultButtonPos == i) {
def_button = button;
}
button.setData("ButtonNo", new Integer(i));
button.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
close(((Number) event.widget.getData("ButtonNo")).intValue());
}
});
}
cBottomArea.getParent().layout(true, true);
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#setAutoCloseInMS(int)
*/
public void setAutoCloseInMS(int autoCloseInMS) {
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#setHtml(java.lang.String)
*/
public void setHtml(String html) {
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#setIconResource(java.lang.String)
*/
public void setIconResource(String resource) {
this.iconResource = resource;
if (dlg != null) {
SWTSkinObjectImage soTopLogo = (SWTSkinObjectImage) dlg.getSkin().getSkinObject("top-logo");
if (soTopLogo != null) {
soTopLogo.setImageByID(iconResource, null);
}
}
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#setRelatedObject(java.lang.Object)
*/
public void setRelatedObject(Object relatedObject) {
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#setRelatedObjects(java.lang.Object[])
*/
public void setRelatedObjects(Object[] relatedObjects) {
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#setRemember(java.lang.String, boolean, java.lang.String)
*/
public void setRemember(String rememberID, boolean rememberByDefault,
String rememberText) {
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#setRememberText(java.lang.String)
*/
public void setRememberText(String rememberText) {
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#setUrl(java.lang.String)
*/
public void setUrl(String url) {
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.UIFunctionsUserPrompter#waitUntilClosed()
*/
public int waitUntilClosed() {
if (opened) {
final AESemaphore2 sem = new AESemaphore2("waitUntilClosed");
Utils.execSWTThread(new AERunnable() {
public void runSupport() {
if (dlg == null) {
sem.release();
return;
}
if (!opened) {
dlg.open();
}
Shell shell = dlg.getShell();
if (shell == null || shell.isDisposed()) {
sem.release();
return;
}
shell.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
sem.release();
}
});
}
});
if (Utils.isThisThreadSWT()) {
// on swt thread, so execSWTThread just ran and we should have a shell
if (dlg != null) {
Shell shell = dlg.getShell();
if (shell != null) {
Display d = shell.getDisplay();
while (!shell.isDisposed()) {
if (!d.readAndDispatch()) {
d.sleep();
}
}
}
return getButtonVal(result);
}
}
sem.reserve();
}
return getButtonVal(result);
}
/* (non-Javadoc)
* @see com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog.SkinnedDialogClosedListener#skinDialogClosed(com.aelitis.azureus.ui.swt.views.skin.SkinnedDialog)
*/
public void skinDialogClosed(SkinnedDialog dialog) {
synchronized (resultListeners) {
int realResult = getButtonVal(result);
for (UserPrompterResultListener l : resultListeners) {
try {
l.prompterClosed(realResult);
} catch (Exception e) {
Debug.out(e);
}
}
}
}
public void setListener(VuzeMessageBoxListener l) {
this.vuzeMessageBoxListener = l;
}
/**
* @deprecated Since buttons can swap around, you should use {@link #closeWithButtonVal(int)}
*/
public void close(int buttonNo) {
synchronized (VuzeMessageBox.this) {
this.closed = true;
this.result = buttonNo;
if (dlg != null) {
dlg.close();
}
}
}
private int getButtonPosFromVal(int buttonVal) {
int pos = buttonVal;
if (buttonVals != null) {
for (int i = 0; i < buttonVals.length; i++) {
int val = buttonVals[i];
if (buttonVal == val) {
pos = i;
break;
}
}
}
return pos;
}
public void closeWithButtonVal(int buttonVal) {
synchronized (VuzeMessageBox.this) {
this.closed = true;
this.result = getButtonPosFromVal(buttonVal);
if (dlg != null) {
dlg.close();
}
}
}
public void addResourceBundle(Class cla, String path, String name) {
synchronized (listRBs) {
if (skin == null) {
listRBs.add(new rbInfo(cla, path, name));
return;
}
}
String sFile = path + name;
ClassLoader loader = cla.getClassLoader();
ResourceBundle subBundle = ResourceBundle.getBundle(sFile,
Locale.getDefault(), loader);
SWTSkinProperties skinProperties = skin.getSkinProperties();
skinProperties.addResourceBundle(subBundle, path, loader);
}
public void setTextIconResource(String resource) {
this.textIconResource = resource;
if (dlg != null) {
SWTSkinObjectImage soIcon = (SWTSkinObjectImage) dlg.getSkin().getSkinObject("text-icon");
if (soIcon != null) {
soIcon.setImageByID(textIconResource, null);
}
}
}
public void addListener(UserPrompterResultListener l) {
if (l == null) {
return;
}
synchronized (resultListeners) {
resultListeners.add(l);
}
}
public void setDefaultButtonByPos(int pos) {
if (dlg == null) {
defaultButtonPos = pos;
}
}
private static class rbInfo {
public rbInfo(Class cla, String path, String name) {
super();
this.cla = cla;
this.path = path;
this.name = name;
}
Class cla;
String path;
String name;
}
}