[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[nebula-dev] [CalendarCombo] Bug and solution
|
Hello,
I'am using the CalendarCombo widget and I have a bug with it and I have
a solution to correct this problem. (See the attached file).
The bug is the following. If I select in the calendar popup 'Today',
then 'None', then 'Today', I have the following exception (I added a
"try ... catch" to see this exception) :
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.<init>(String.java:202)
at org.eclipse.swt.internal.win32.TCHAR.toString(TCHAR.java:115)
at org.eclipse.swt.widgets.Combo.getText(Combo.java:846)
at
org.eclipse.nebula.widgets.calendarcombo.CalendarCombo.setText(CalendarCombo.java:1127)
at
org.eclipse.nebula.widgets.calendarcombo.CalendarCombo.updateDate(CalendarCombo.java:1566)
at
org.eclipse.nebula.widgets.calendarcombo.CalendarCombo.access$20(CalendarCombo.java:1565)
at
org.eclipse.nebula.widgets.calendarcombo.CalendarCombo$17.dateChanged(CalendarCombo.java:1461)
at
org.eclipse.nebula.widgets.calendarcombo.CalendarComposite.notifyListeners(CalendarComposite.java:732)
at
org.eclipse.nebula.widgets.calendarcombo.CalendarComposite.notifyListeners(CalendarComposite.java:745)
at
org.eclipse.nebula.widgets.calendarcombo.CalendarComposite.clickedTodayButton(CalendarComposite.java:214)
at
org.eclipse.nebula.widgets.calendarcombo.CalendarComposite.externalClick(CalendarComposite.java:770)
at
org.eclipse.nebula.widgets.calendarcombo.CalendarCombo$9.handleEvent(CalendarCombo.java:839)
I have this exception because in the class 'CalendarCombo' the method
'Combo.setText(String )' is used to set the text in the Combo. I think
that the method 'Combo.add(...)' (like in the method
'CalendarCombosetText(...)') must be always used to set the text.
In attached file, there is the CalendarCombo with a solution : add a
method 'setComboText(String )' to set the text for the Combo (flat or
not) and I am using only this method in the CalendarCombo class.
Jérôme
/*******************************************************************************
* Copyright (c) Emil Crumhorn - Hexapixel.com - emil.crumhorn@xxxxxxxxx
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* emil.crumhorn@xxxxxxxxx - initial API and implementation
*******************************************************************************/
package org.eclipse.nebula.widgets.calendarcombo;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.DragDetectListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.HelpListener;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MenuDetectListener;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.MouseWheelListener;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;
/**
* <b>CalendarCombo - SWT Widget - 2005-2008. Version 1.0. © Emil Crumhorn
* - emil dot crumhorn at gmail dot com.</b>
* <p>
* <b>Website</b><br>
* If you want more info or more documentation, please visit: <a
* href="http://www.hexapixel.com/">http://www.hexapixel.com</a>
* <p>
* <b>Description</b><br>
* CalendarCombo is a widget that opens a calendar when dropped down. The
* calendar is modelled after Microsoft Outlook's calendar widget and acts and
* behaves exactly the same (and it is also theme based). The combo is not based
* on CCombo (as many other custom implementations), but is instead attached to
* the native Combo box.
* <p>
* <b>Example Creation Code</b><br>
* <code>
* CalendarCombo cCombo = new CalendarCombo(parentControl, SWT.READ_ONLY);<br>
* ...<br>
* </code>
* <p>
* <b>Another example using depending combos and date range selection on the
* first combo</b><br>
* <code>
* CalendarCombo cComboStart = new CalendarCombo(parentControl, SWT.READ_ONLY, true);<br>
* CalendarCombo cComboEnd = new CalendarCombo(parentControl, SWT.READ_ONLY);<br>
* cComboStart.setDependingCombo(cComboEnd);<br>
* </code> <br>
* This will cause the end date for the date range selection to be populated in
* the cComboEnd combo.
* <p>
* <b>Customizing</b><br>
* There are two interfaces that are of importance for customizing, one is
* IColorManager and the other is ISettings. Let's start with the IColorManager.
* <p>
* <b>IColorManager</b><br>
* If you don't specify a color manager, the DefaultColorManager will be used.
* The color manager's job is to return colors to the method that is painting
* all the actual days and months etc. The colors that are returned from the
* ColorManager will determine everything as far as looks go.
* <p>
* <b>ISettings</b><br>
* To control the spacing between dates, various formats and text values, you
* will want to implement the ISettings interface. If you don't specify one,
* DefaultSettings will be used.
*
* @author Emil Crumhorn
* @version 1.1.2008.11.25
*
*/
public class CalendarCombo extends Composite {
// the main combo box
private Combo mCombo;
private FlatCalendarCombo mFlatCombo;
private Composite mComboControl;
private int mComboStyle = SWT.NONE;
// the shell holding the CalendarComposite
private Shell mCalendarShell;
private Listener mKillListener;
private Listener mFilterListenerFocusIn;
private Composite mParentComposite;
// values for determining when the last view of the mCalendarShell was.
// this is to determine how quick clicks should behave
private long mLastShowRequest = 0;
private long mLastKillRequest = 0;
private boolean mAllowTextEntry;
private CalendarCombo mDependingCombo;
private CalendarComposite mCalendarComposite;
private Calendar mStartDate;
private Calendar mEndDate;
private IColorManager mColorManager;
private ISettings mSettings;
private ArrayList mListeners;
private Calendar mDisallowBeforeDate;
private Calendar mDisallowAfterDate;
private boolean isReadOnly;
private boolean isFlat;
private int arrowButtonWidth;
private boolean mAllowDateRange;
private Calendar mCarbonPrePopupDate;
private Listener mKeyDownListener;
private boolean mParsingDate;
private int mLastFireTime;
private Calendar mLastNotificationDate;
private Listener mOobClickListener;
protected static final boolean OS_CARBON = "carbon".equals(SWT.getPlatform());
protected static final boolean OS_GTK = "gtk".equals(SWT.getPlatform());
protected static final boolean OS_WINDOWS = "win32".equals(SWT.getPlatform());
/*
* // Windows JNI Code for making a non-activated canvas, for reference if
* searching MSDN int extStyle = OS.GetWindowLong(canvas.handle,
* OS.GWL_EXSTYLE); extStyle = extStyle | 0x80000;
* OS.SetWindowLong(canvas.handle, OS.GWL_EXSTYLE, extStyle); 0x008000000 =
* WS_EX_NOACTIVATE;
*/
/**
* Creates a new calendar combo box with the given style.
*
* @param parent
* Parent control
* @param style
* Combo style
*/
public CalendarCombo(Composite parent, int style) {
super(parent, checkStyle(style));
this.mComboStyle = style;
this.mParentComposite = parent;
init();
}
/**
* Creates a new calendar combo box with the given style.
*
* @param parent
* Parent control
* @param style
* Combo style
* @param allowDateRange
* Whether to allow date range selection (note that if there is
* no depending CalendarCombo set you will have to deal with the
* date range event yourself).
*/
public CalendarCombo(Composite parent, int style, boolean allowDateRange) {
super(parent, checkStyle(style));
this.mComboStyle = style;
this.mParentComposite = parent;
this.mAllowDateRange = allowDateRange;
init();
}
/**
* Creates a new calendar mCombo box with the given style, ISettings and
* IColorManager implementations.
*
* @param parent
* Parent control
* @param style
* Combo style
* @param settings
* ISettings implementation
* @param colorManager
* IColorManager implementation
*/
public CalendarCombo(Composite parent, int style, ISettings settings, IColorManager colorManager) {
super(parent, checkStyle(style));
this.mComboStyle = style;
this.mParentComposite = parent;
this.mSettings = settings;
this.mColorManager = colorManager;
init();
}
/**
* Creates a new calendar mCombo box with the given style, ISettings and
* IColorManager implementations.
*
* @param parent
* Parent control
* @param style
* Combo style
* @param settings
* ISettings implementation
* @param colorManager
* IColorManager implementation
* @param allowDateRange
* Whether to allow date range selection (note that if there is
* no depending CalendarCombo set you will have to deal with the
* date range event yourself).
*/
public CalendarCombo(Composite parent, int style, ISettings settings, IColorManager colorManager, boolean allowDateRange) {
super(parent, checkStyle(style));
this.mComboStyle = style;
this.mParentComposite = parent;
this.mSettings = settings;
this.mColorManager = colorManager;
this.mAllowDateRange = allowDateRange;
init();
}
/**
* Lets you create a depending CalendarCombo box, which, when no dates are
* set on the current one will set the starting date when popped up to be
* the date of the pullDateFrom CalendarCombo, should that box have a date
* set in it.
*
* @param parent
* @param style
* @param dependingCombo
* CalendarCombo from where start date is pulled when no date has
* been set locally.
*/
public CalendarCombo(Composite parent, int style, CalendarCombo dependingCombo) {
super(parent, checkStyle(style));
this.mParentComposite = parent;
this.mDependingCombo = dependingCombo;
this.mComboStyle = style;
init();
}
/**
* Lets you create a depending CalendarCombo box, which, when no dates are
* set on the current one will set the starting date when popped up to be
* the date of the pullDateFrom CalendarCombo, should that box have a date
* set in it.
*
* When the depending combo is set and the allowDateRange flag is true, the
* depending combo will be the recipient of the end date of any date range
* selection.
*
* @param parent
* @param style
* @param dependingCombo
* CalendarCombo from where start date is pulled when no date has
* been set locally.
* @param allowDateRange
* Whether to allow date range selection
*/
public CalendarCombo(Composite parent, int style, CalendarCombo dependingCombo, boolean allowDateRange) {
super(parent, checkStyle(style));
this.mParentComposite = parent;
this.mDependingCombo = dependingCombo;
this.mComboStyle = style;
this.mAllowDateRange = allowDateRange;
init();
}
/**
* Lets you create a depending CalendarCombo box, which, when no dates are
* set on the current one will set the starting date when popped up to be
* the date of the pullDateFrom CalendarCombo, should that box have a date
* set in it.
*
* @param parent
* @param style
* @param dependingCombo
* CalendarCombo from where start date is pulled when no date has
* been set locally.
* @param settings
* ISettings implementation
* @param colorManager
* IColorManager implementation
*/
public CalendarCombo(Composite parent, int style, CalendarCombo dependingCombo, ISettings settings, IColorManager colorManager) {
super(parent, checkStyle(style));
this.mParentComposite = parent;
this.mDependingCombo = dependingCombo;
this.mComboStyle = style;
this.mSettings = settings;
this.mColorManager = colorManager;
init();
}
/**
* Lets you create a depending CalendarCombo box, which, when no dates are
* set on the current one will set the starting date when popped up to be
* the date of the pullDateFrom CalendarCombo, should that box have a date
* set in it.
*
* When the depending combo is set and the allowDateRange flag is true, the
* depending combo will be the recipient of the end date of any date range
* selection.
*
* @param parent
* @param style
* @param dependingCombo
* CalendarCombo from where start date is pulled when no date has
* been set locally.
* @param settings
* ISettings implementation
* @param colorManager
* IColorManager implementation
* @param allowDateRange
* Whether to allow date range selection
*/
public CalendarCombo(Composite parent, int style, CalendarCombo dependingCombo, ISettings settings, IColorManager colorManager, boolean allowDateRange) {
super(parent, checkStyle(style));
this.mParentComposite = parent;
this.mDependingCombo = dependingCombo;
this.mComboStyle = style;
this.mSettings = settings;
this.mColorManager = colorManager;
init();
}
// remove styles we don't allow
private static int checkStyle(int style) {
int mask = SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.MULTI | SWT.NO_FOCUS | SWT.CHECK | SWT.VIRTUAL | SWT.FLAT;
int newStyle = style & mask;
return newStyle;
}
// lay out everything and add all our listeners
private void init() {
isReadOnly = ((mComboStyle & SWT.READ_ONLY) != 0);
isFlat = ((mComboStyle & SWT.FLAT) != 0);
mListeners = new ArrayList();
// if click happens on a control that is not us, we kill
mOobClickListener = new Listener() {
public void handleEvent(Event event) {
if (!isCalendarVisible())
return;
if (Display.getDefault().getCursorControl() != mCalendarComposite) {
kill(44);
}
}
};
if (mColorManager == null)
mColorManager = new DefaultColorManager();
if (mSettings == null)
mSettings = new DefaultSettings();
arrowButtonWidth = mSettings.getWindowsButtonWidth();
if (OS_CARBON)
arrowButtonWidth = mSettings.getCarbonButtonWidth();
else if (OS_GTK)
arrowButtonWidth = mSettings.getGTKButtonWidth();
GridLayout gl = new GridLayout();
gl.horizontalSpacing = 0;
gl.verticalSpacing = 0;
gl.marginWidth = 0;
gl.marginHeight = 0;
setLayout(gl);
if (isFlat) {
mFlatCombo = new FlatCalendarCombo(this, this, mComboStyle | SWT.FLAT);
mFlatCombo.setVisibleItemCount(0);
mFlatCombo.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
mComboControl = mFlatCombo;
}
else {
mCombo = new Combo(this, mComboStyle);
mCombo.setVisibleItemCount(0);
mCombo.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
mComboControl = mCombo;
}
// when a user types in a date we parse it when they traverse away in
// any sense or form (focus lost etc)
if (!isReadOnly) {
Listener traverseListener = new Listener() {
public void handleEvent(Event event) {
if (event.detail == 16 || event.detail == 8 || event.detail == 4 || event.detail == 0) {
parseTextDate();
}
}
};
// deal with traverse-away/in/return events to parse dates
mComboControl.addListener(SWT.Traverse, traverseListener);
mComboControl.addListener(SWT.FocusOut, traverseListener);
mKeyDownListener = new Listener() {
public void handleEvent(Event event) {
// if event didn't happen on this combo, ignore it
if (isFlat) {
if (event.widget != mFlatCombo.getTextControl())
return;
}
else {
if (event.widget != mCombo) {
return;
}
}
if (mSettings.keyboardNavigatesCalendar()) {
if (event.keyCode == SWT.ARROW_DOWN) {
Control ctrl = (isFlat ? (Control) mFlatCombo.getTextControl() : mCombo);
if (Display.getDefault().getFocusControl() == ctrl) {
if (!isCalendarVisible())
showCalendar();
else {
mCalendarComposite.keyPressed(event.keyCode, event.stateMask);
event.doit = false;
}
}
}
else {
if (isCalendarVisible()) {
mCalendarComposite.keyPressed(event.keyCode, event.stateMask);
// eat event or cursor will jump around in combo
// as well
event.doit = false;
}
}
}
else {
boolean acceptedEvent = (event.keyCode == SWT.ARROW_DOWN || event.keyCode == SWT.ARROW_UP);
if (OS_CARBON) {
acceptedEvent = (event.character == mSettings.getCarbonArrowDownChar() || event.character == mSettings.getCarbonArrowUpChar());
}
if (acceptedEvent) {
boolean up = event.keyCode == SWT.ARROW_UP;
if (OS_CARBON)
up = event.character == mSettings.getCarbonArrowUpChar();
int cursorLoc = isFlat ? mFlatCombo.getSelection().x : mCombo.getSelection().x;
// first, parse the date, we don't care if it's some
// fantastic format we can parse, parse it again
parseTextDate();
// once it's parsed, set it to the default format,
// that way we KNOW where certain parts of the date
// are
if (mStartDate != null) {
setComboText(DateHelper.getDate(mStartDate, mSettings.getDateFormat()));
String df = mSettings.getDateFormat();
event.doit = false;
if (isFlat)
mFlatCombo.setSelection(new Point(cursorLoc, cursorLoc));
else
mCombo.setSelection(new Point(cursorLoc, cursorLoc));
// split the date format. we do this as a date
// format of M/d/yyyy for example can still have
// 2 digits as M or d .
String separatorChar = null;
char[] accepted = mSettings.getAcceptedDateSeparatorChars();
for (int i = 0; i < accepted.length; i++) {
if (df.indexOf(String.valueOf(accepted[i])) > -1) {
separatorChar = String.valueOf(accepted[i]);
}
}
int sectionStart = 0;
int sectionEnd = 0;
int splitCount = 0;
// get the format
String oneChar = "";
if (separatorChar != null) {
// now find how many separator chars we are
// from the left side of the date in the box
// to where the cursor is, that will tell us
// what part of
// the date format we're on
String comboText = isFlat ? mFlatCombo.getText() : mCombo.getText();
for (int i = 0; i < comboText.length(); i++) {
if (i >= cursorLoc)
break;
if (comboText.charAt(i) == separatorChar.charAt(0))
splitCount++;
}
StringTokenizer st = new StringTokenizer(df, separatorChar);
int count = 0;
while (st.hasMoreTokens()) {
String tok = st.nextToken();
if (count == splitCount) {
oneChar = tok;
break;
}
count++;
}
}
else {
oneChar = mSettings.getDateFormat().substring(cursorLoc, cursorLoc + 1);
// get the whole part, bit tricky I suppose,
// but
// we fetch everything that matches the
// format
// at the position we're at, easy enough
StringBuffer buf = new StringBuffer();
int start = cursorLoc;
while (start >= 0) {
if (mSettings.getDateFormat().charAt(start) == oneChar.charAt(0)) {
buf.append(mSettings.getDateFormat().charAt(start));
}
else {
break;
}
start--;
}
start = cursorLoc + 1;
while (start < mSettings.getDateFormat().length()) {
if (mSettings.getDateFormat().charAt(start) == oneChar.charAt(0)) {
buf.append(mSettings.getDateFormat().charAt(start));
}
else {
break;
}
start++;
}
sectionStart = mSettings.getDateFormat().indexOf(buf.toString());
sectionEnd = sectionStart + buf.toString().length();
}
// now we now what to increase/decrease, lets do
// it
int calType = -1;
switch (oneChar.charAt(0)) {
case 'G':
calType = Calendar.ERA;
break;
case 'y':
calType = Calendar.YEAR;
break;
case 'M':
calType = Calendar.MONTH;
break;
case 'd':
calType = Calendar.DAY_OF_MONTH;
break;
case 'E':
calType = Calendar.DAY_OF_WEEK;
break;
case 'D':
calType = Calendar.DAY_OF_YEAR;
break;
case 'F':
calType = Calendar.DATE;
break;
case 'h':
calType = Calendar.HOUR;
break;
case 'm':
calType = Calendar.MINUTE;
break;
case 's':
calType = Calendar.SECOND;
break;
case 'S':
calType = Calendar.MILLISECOND;
break;
case 'w':
calType = Calendar.WEEK_OF_YEAR;
break;
case 'W':
calType = Calendar.WEEK_OF_MONTH;
break;
case 'a':
calType = Calendar.AM_PM;
break;
case 'k':
calType = Calendar.HOUR_OF_DAY;
break;
case 'K':
// ?
break;
case 'z':
calType = Calendar.ZONE_OFFSET;
break;
}
if (calType != -1) {
mStartDate.add(calType, up ? 1 : -1);
String newDate = DateHelper.getDate(mStartDate, mSettings.getDateFormat());
setComboText(newDate);
if (separatorChar != null) {
// we need to update the selection after
// we've set the date
// figure out cursor location, now we
// have to use the date in the box again
StringTokenizer st = new StringTokenizer(newDate, separatorChar);
int count = 0;
boolean stop = false;
while (st.hasMoreTokens()) {
String tok = st.nextToken();
// we found our section
if (count == splitCount) {
sectionEnd = sectionStart + tok.length();
stop = true;
break;
}
// if we're stopping, break out
if (stop)
break;
// add on separator chars for each
// loop iteration post 0
sectionStart += 1;
// and token length
sectionStart += tok.length();
count++;
}
}
// set the selection for us
if (isFlat) {
mFlatCombo.setSelection(new Point(sectionStart, sectionEnd));
}
else {
mCombo.setSelection(new Point(sectionStart, sectionEnd));
}
}
}
}
}
}
};
Display.getDefault().addFilter(SWT.KeyDown, mKeyDownListener);
}
if (isFlat) {
mComboControl.addListener(SWT.FocusOut, new Listener() {
public void handleEvent(Event event) {
kill(98);
}
});
}
mComboControl.addListener(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
// click in the text area? ignore
if (!isFlat) {
if (isTextAreaClick(event)) {
if (isCalendarVisible())
kill(16);
return;
}
}
// kill calendar if visible and do nothing else
if (isCalendarVisible()) {
kill(15);
return;
}
// a very small time between the close and the open means it was
// a click on the
// arrow down to close, and we don't open it again in that case.
// The next click will open.
// this is the expected behavior.
mLastShowRequest = Calendar.getInstance(mSettings.getLocale()).getTimeInMillis();
long diff = mLastKillRequest - mLastShowRequest;
if (diff > -100 && diff < 0)
return;
showCalendar();
}
});
mKillListener = new Listener() {
public void handleEvent(Event event) {
if (event.keyCode == SWT.ESC) {
kill(77);
return;
}
// ignore arrow down events for killing popup
if (event.keyCode == SWT.ARROW_DOWN || event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_LEFT || event.keyCode == SWT.ARROW_RIGHT
|| event.keyCode == SWT.CR || event.keyCode == SWT.LF)
return;
kill(1);
}
};
int[] comboEvents = {
SWT.Dispose, SWT.Move, SWT.Resize
};
for (int i = 0; i < comboEvents.length; i++) {
this.addListener(comboEvents[i], mKillListener);
}
int[] arrowEvents = {
SWT.Selection
};
for (int i = 0; i < arrowEvents.length; i++) {
mComboControl.addListener(arrowEvents[i], mKillListener);
}
mFilterListenerFocusIn = new Listener() {
public void handleEvent(Event event) {
if (OS_CARBON) {
Widget widget = event.widget;
if (widget instanceof CalendarComposite == false)
kill(2);
// on mac, select all text in combo if we are the control that gained focus
if (mComboControl == Display.getDefault().getFocusControl()) {
if (isFlat) {
mFlatCombo.getTextControl().selectAll();
}
else {
mCombo.setSelection(new Point(0, mCombo.getText().length()));
}
}
} else {
long now = Calendar.getInstance(mSettings.getLocale()).getTimeInMillis();
long diff = now - mLastShowRequest;
if (diff > 0 && diff < 100)
return;
if (!isCalendarVisible())
return;
// don't force focus, user clicked another control, let it grab the focus or it'll be odd behavior
if (!isFlat)
kill(3, true);
}
}
};
Shell parentShell = mParentComposite.getShell();
if (parentShell != null) {
parentShell.addControlListener(new ControlListener() {
public void controlMoved(ControlEvent e) {
kill(4);
}
public void controlResized(ControlEvent e) {
kill(5);
}
});
parentShell.addListener(SWT.Deactivate, new Listener() {
public void handleEvent(Event event) {
Point mouseLoc = Display.getDefault().getCursorLocation();
// with no focus shells, buttons will steal focus, and cause
// deactivate events when clicked
// so if the deactivate came from a mouse being over any of
// our buttons, that is the same as
// if we clicked them.
if (mCalendarComposite != null && mCalendarComposite.isDisposed() == false)
mCalendarComposite.externalClick(mouseLoc);
if (!isFlat)
kill(6);
}
});
parentShell.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
kill(7);
}
});
}
Display.getDefault().addFilter(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
// This may seem odd, but if the event is the CalendarCombo, we
// actually clicked outside the widget and the CalendarComposite
// area, meaning -
// we clicked outside our widget, so we close it.
if (event.widget instanceof CalendarCombo) {
kill(8);
mComboControl.setFocus();
}
}
});
// remove listener when mCombo is disposed
Display.getDefault().addFilter(SWT.FocusIn, mFilterListenerFocusIn);
mComboControl.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent event) {
Display.getDefault().removeFilter(SWT.FocusIn, mFilterListenerFocusIn);
if (mKeyDownListener != null)
Display.getDefault().removeFilter(SWT.KeyDown, mKeyDownListener);
if (mSettings.getCarbonDrawFont() != null)
mSettings.getCarbonDrawFont().dispose();
if (mSettings.getWindowsMonthPopupDrawFont() != null)
mSettings.getWindowsMonthPopupDrawFont().dispose();
}
});
// mac's editable combos behave differently
if (OS_CARBON) {
// this code seems obsolete as of June 24th 2008, Allow text input
// on Mac, we parse it anyways now, which we didn't do prior
// leaving code in for a while to remind myself
/*
* mCombo.addVerifyListener(new VerifyListener() { public void
* verifyText(VerifyEvent event) { if (isCalendarVisible() ||
* mAllowTextEntry) { ; } else { event.doit = false; } } });
*/
// this is the most messed up thing ever, but it works. Basically,
// OSX will pop up a combo of 1 item to let you pick it
// even when it's blantantly obvious that you can only pick that one
// item.. duh.. Anyway, the Paint event actually fires PRIOR to the
// combo
// opening, and our "cure" to the popup issue is to quickly remove
// the item from the combo before it does open, thus, it doesn't
// show the selector list,
// but our popup instead. The side effect is that the combo appears
// blank while the calendar is open. But as we reset the date when
// no selection has been made, it's all good! It ain't pretty, but
// it does the job
if (isReadOnly) {
if (isFlat) {
mFlatCombo.addListener(SWT.Paint, new Listener() {
public void handleEvent(Event event) {
mCarbonPrePopupDate = getDate();
// mFlatCombo.removeAll();
}
});
}
else {
mCombo.addListener(SWT.Paint, new Listener() {
public void handleEvent(Event event) {
mCarbonPrePopupDate = getDate();
mCombo.removeAll();
}
});
}
}
}
parentShell.addShellListener(new ShellListener() {
public void shellActivated(ShellEvent event) {
}
public void shellClosed(ShellEvent event) {
// shell killed
kill(9);
}
public void shellDeactivated(ShellEvent event) {
}
public void shellDeiconified(ShellEvent event) {
}
public void shellIconified(ShellEvent event) {
// shell no longer in focus (like.. WindowsKey + M on WinXP or
// such)
kill(10);
}
});
}
// parses the date, and really tries
private void parseTextDate() {
// listeners by users can cause infinite loops as we notify, they set on
// notify, etc, so don't allow parsing if we haven't finished yet
if (mParsingDate)
return;
try {
mParsingDate = true;
String comboText = (isFlat ? mFlatCombo.getText() : mCombo.getText());
if (comboText.length() == 0) {
mStartDate = null;
setText("");
notifyDateChanged();
return;
}
try {
mStartDate = DateHelper.getDate(comboText, mSettings.getDateFormat(), mSettings.getLocale());
updateDate();
notifyDateChanged();
// System.err.println("Got here 1 - Settings parse");
}
catch (Exception err) {
// try the locale
try {
mStartDate = DateHelper.parseDate(comboText, mSettings.getLocale());
updateDate();
notifyDateChanged();
// System.err.println("Got here 2 - Locale parse");
}
catch (Exception deeper) {
try {
mStartDate = DateHelper.parseDateHard(comboText, mSettings.getLocale());
updateDate();
notifyDateChanged();
// System.err.println("Got here 3 - Hard parse");
}
catch (Exception deepest) {
// System.err.println("Got here 4 - Failed parse");
List otherFormats = mSettings.getAdditionalDateFormats();
if (otherFormats != null) {
try {
for (int i = 0; i < otherFormats.size(); i++) {
try {
String format = (String) otherFormats.get(i);
Date date = DateHelper.getDate(comboText, format);
// success
setDate(date);
updateDate();
notifyDateChanged();
return;
}
catch (Exception failed) {
// keep trying
}
}
}
catch (Exception err2) {
// don't care
}
}
// unparseable date, set the last used date if any,
// otherwise set nodateset text
if (mStartDate != null)
setDate(mStartDate);
else {
setComboText(mSettings.getNoDateSetText());
}
}
}
}
}
catch (Exception err) {
err.printStackTrace();
}
finally {
mParsingDate = false;
}
}
private void notifyDateChanged() {
// don't notify on same dates
if (mLastNotificationDate == null && mStartDate == null)
return;
if (mLastNotificationDate != null && mStartDate != null) {
if (DateHelper.sameDate(mLastNotificationDate, mStartDate))
return;
}
for (int i = 0; i < mListeners.size(); i++) {
try {
((ICalendarListener) mListeners.get(i)).dateChanged(mStartDate);
}
catch (Exception err) {
err.printStackTrace();
}
}
}
// checks whether a click was actually in the text area of a combo and not
// on the arrow button. This is a hack by all means,
// as there is (currently) no way to get the actual button from a combo.
private boolean isTextAreaClick(Event event) {
// read-only combos open on click anywhere
if (isReadOnly)
return false;
Point size = isFlat ? mFlatCombo.getSize() : mCombo.getSize();
Rectangle rect = null;
rect = new Rectangle(0, 0, size.x - arrowButtonWidth, size.y);
if (isInside(event.x, event.y, rect))
return true;
return false;
}
// check whether a pixel value is inside a rectangle
private boolean isInside(int x, int y, Rectangle rect) {
if (rect == null)
return false;
return x >= rect.x && y >= rect.y && x <= (rect.x + rect.width) && y <= (rect.y + rect.height);
}
/**
* Sets the current date. Date will be automatically displayed in the text
* area of the combo according to the defined date format (in settings).
*
* @param date
* Date to set
*/
public synchronized void setDate(Date date) {
checkWidget();
Calendar cal = Calendar.getInstance(mSettings.getLocale());
cal.setTime(date);
setDate(cal);
}
/**
* Sets the current date. Date will be automatically displayed in the text
* area of the combo according to the defined date format (in settings).
*
* @param cal
* Calendar to set
*/
public synchronized void setDate(Calendar cal) {
checkWidget();
setText(DateHelper.getDate(cal, mSettings.getDateFormat()));
this.mStartDate = cal;
}
/**
* Sets the text in the combo area to the given value. Do note that if you
* set a text that is a non-pareseable date string according to the
* currently set date format, that string will be replaced or removed when
* the user opens the popup. This is mainly for disabled combos or combos
* where you need to add additional control to what's displayed in the text
* area.
*
* @param text
* Text to display
*/
public synchronized void setText(final String text) {
checkWidget();
String txt = isFlat ? mFlatCombo.getText() : mCombo.getText();
if (txt.equals(text))
return;
mAllowTextEntry = true;
setComboText(text);
mAllowTextEntry = false;
}
private void setComboText(String text) {
if (isFlat) {
mFlatCombo.setText(text);
}
else {
mCombo.removeAll();
mCombo.add(text);
mCombo.select(0);
}
}
private synchronized void kill(int debug) {
kill(debug, false);
}
// kills the popup area and unhooks various listeners, takes an integer so
// that we can debug where the close comes from easier
private synchronized void kill(int debug, boolean skipFocus) {
if (mCalendarComposite == null)
return;
if (mCalendarComposite.isDisposed())
return;
if (mCalendarComposite != null && mCalendarComposite.isMonthPopupActive())
return;
// System.err.println(debug);
if (mCalendarShell != null && !mCalendarShell.isDisposed()) {
mLastKillRequest = Calendar.getInstance(mSettings.getLocale()).getTimeInMillis();
mCalendarShell.setVisible(false);
mCalendarShell.dispose();
}
Display.getDefault().removeFilter(SWT.KeyDown, mKillListener);
Display.getDefault().removeFilter(SWT.MouseDown, mOobClickListener);
if (mComboControl != null && !mComboControl.isDisposed()) {
mComboControl.setCapture(false);
// have to traverse escape key after the fake popup is closed or the
// "0 length" popup will have focus
// traversing forces it to close
mComboControl.traverse(SWT.TRAVERSE_ESCAPE);
// if (getDate().length() != 0)
// setText(DateHelper.getFormattedDate(DateHelper.getDate(getDate(),
// mDateFormat), mDateFormat));
}
if (OS_CARBON) {
if (mCarbonPrePopupDate != null)
setDate(mCarbonPrePopupDate);
}
if (!skipFocus) {
if (isFlat) {
mFlatCombo.getTextControl().setFocus();
}
else {
mCombo.setFocus();
}
}
}
private boolean isCalendarVisible() {
if (mCalendarShell != null && !mCalendarShell.isDisposed())
return true;
return false;
}
/**
* Pops open the calendar popup.
*/
public void openCalendar() {
checkWidget();
if (isCalendarVisible())
return;
showCalendar();
}
/**
* Closes the calendar popup.
*/
public void closeCalendar() {
checkWidget();
if (!isCalendarVisible())
return;
kill(99);
}
/**
* Returns the set date as the raw String representation that is currently
* displayed in the combo.
*
* @return String date
*/
public String getDateAsString() {
checkWidget();
String text = isFlat ? mFlatCombo.getText() : mCombo.getText();
if (text.equals(""))
return "";
return text;
}
/**
* Returns the currently set date.
*
* @return Calendar of date selection or null.
*/
public Calendar getDate() {
checkWidget();
if (!isReadOnly)
parseTextDate();
return mStartDate;
}
/*
* private void setDateBasedOnComboText() { try { Date d =
* DateHelper.getDate(isFlat ? mFlatCombo.getText() : mCombo.getText(),
* mSettings.getDateFormat()); setDate(d); } catch (Exception err) { // we
* don't care } }
*/
// shows the calendar area
public synchronized void showCalendar() {
try {
// this is part of the OSX issue where the popup for a combo is
// shown even if there is only 1 item to select (dumb).
// as we remove the date just prior to the popup opening, here, we
// add it again, so it doesn't look like anything happened to the
// user
// when in fact we removed and added something in the blink of an
// eye, just so that the combo would not open its own popup. This
// seems to work
// without a hitch -- fix: June 21, 2008
if (OS_CARBON && isReadOnly && mCarbonPrePopupDate != null)
setDate(mCarbonPrePopupDate);
// bug fix: Apr 18, 2008 - if we do various operations prior to
// actually fetching any newly entered text into the
// (non-read only) combo, we'll lose that edit, so fetch the combo
// text now so that we can check it later down in the code
// reported by: B. Haje
parseTextDate();
String comboText = isFlat ? mFlatCombo.getText() : mCombo.getText();
mComboControl.setCapture(true);
// some weird bug with opening, selecting, closing, then opening
// again, which blanks out the mCombo the first time around..
if (!isFlat)
mCombo.select(0);
// kill any old
if (isCalendarVisible()) {
// bug fix part #2, apr 23. Repeated klicking open/close will
// get here, so we need to do the same bug fix as before but
// somewhat differently
// as we need to update the date object as well. This is
// basically only for non-read-only combos, but the fix is
// universally applicable.
setComboText(comboText);
parseTextDate();
kill(11);
return;
}
mComboControl.setFocus();
// bug fix: Apr 18, 2008 (see above)
// the (necessary) setFocus call above for some reason screws up any
// text entered by the user, so we actually have to set the text
// back onto the combo, despite the fact we pulled the data just a
// few lines ago.
setComboText(comboText);
Display.getDefault().addFilter(SWT.KeyDown, mKillListener);
Display.getDefault().addFilter(SWT.MouseDown, mOobClickListener);
mCalendarShell = new Shell(Display.getDefault().getActiveShell(), SWT.ON_TOP | SWT.NO_TRIM | SWT.NO_FOCUS);
mCalendarShell.setLayout(new FillLayout());
if (OS_CARBON)
mCalendarShell.setSize(mSettings.getCalendarWidthMacintosh(), mSettings.getCalendarHeightMacintosh());
else
mCalendarShell.setSize(mSettings.getCalendarWidth(), mSettings.getCalendarHeight());
mCalendarShell.addShellListener(new ShellListener() {
public void shellActivated(ShellEvent event) {
}
public void shellClosed(ShellEvent event) {
// shell killed
kill(12);
}
public void shellDeactivated(ShellEvent event) {
}
public void shellDeiconified(ShellEvent event) {
}
public void shellIconified(ShellEvent event) {
// shell no longer in focus (like.. WindowsKey + M on WinXP
// or such)
kill(13);
}
});
// if no date has been set, and we have another calendar widget to
// pull from, grab that date.
// if we do have a date set, load it as an object we can actually
// use.
Calendar pre = null;
if (comboText != null && comboText.length() > 1) {
try {
Date dat = DateHelper.getDate(comboText, mSettings.getDateFormat());
if (dat != null) {
pre = Calendar.getInstance(mSettings.getLocale());
pre.setTime(dat);
}
}
catch (Exception err) {
List otherFormats = mSettings.getAdditionalDateFormats();
if (otherFormats != null) {
boolean dateSet = false;
try {
for (int i = 0; i < otherFormats.size(); i++) {
String format = (String) otherFormats.get(i);
Date date = DateHelper.getDate(comboText, format);
// success
setDate(date);
Calendar cal = Calendar.getInstance(mSettings.getLocale());
cal.setTime(date);
pre = cal;
dateSet = true;
break;
}
}
catch (Exception err2) {
// don't care
// err2.printStackTrace();
}
if (!dateSet) {
// unparseable date, set the last used date if any,
// otherwise set nodateset text
if (mStartDate != null)
setDate(mStartDate);
else {
setComboText(mSettings.getNoDateSetText());
}
}
}
else {
// unparseable date, set the last used date if any,
// otherwise set nodateset text
if (mStartDate != null)
setDate(mStartDate);
else {
setComboText(mSettings.getNoDateSetText());
}
}
}
}
else {
if (mDependingCombo != null) {
// we need to pull the date from the depending combo's text
// area as it may be non-read-only, so we can't rely on the
// date
Calendar date = null;
try {
Date d = DateHelper.getDate(mDependingCombo.getCombo().getText(), mSettings.getDateFormat());
date = Calendar.getInstance(mSettings.getLocale());
date.setTime(d);
}
catch (Exception err) {
date = mDependingCombo.getDate();
}
if (date != null) {
pre = Calendar.getInstance(mSettings.getLocale());
pre.setTime(date.getTime());
}
}
}
// create the calendar composite
mCalendarComposite = new CalendarComposite(mCalendarShell, pre, mDisallowBeforeDate, mDisallowAfterDate, mColorManager, mSettings, mAllowDateRange, mStartDate,
mEndDate);
for (int i = 0; i < mListeners.size(); i++) {
ICalendarListener listener = (ICalendarListener) mListeners.get(i);
mCalendarComposite.addCalendarListener(listener);
}
mCalendarComposite.addMainCalendarListener(new ICalendarListener() {
public void dateChanged(Calendar date) {
mAllowTextEntry = true;
if (!isFlat)
mCombo.removeAll();
if (OS_CARBON)
mCarbonPrePopupDate = date;
mStartDate = date;
if (date == null) {
setText("");
}
else {
updateDate();
}
mAllowTextEntry = false;
}
public void dateRangeChanged(Calendar start, Calendar end) {
mAllowTextEntry = true;
if (!isFlat)
mCombo.removeAll();
mStartDate = start;
if (OS_CARBON)
mCarbonPrePopupDate = start;
mEndDate = end;
if (start == null) {
setText("");
}
else {
updateDate();
}
mAllowTextEntry = false;
if (mDependingCombo != null) {
if (end != null)
mDependingCombo.setDate(end);
else
mDependingCombo.setText("");
}
}
public void popupClosed() {
kill(14);
}
});
// figure out where to put the calendar composite shell
Point calLoc = mComboControl.getLocation();
Point size = mComboControl.getSize();
Point loc = null;
if (mSettings.showCalendarInRightCorner())
loc = new Point(calLoc.x + size.x - mCalendarShell.getSize().x, calLoc.y + size.y);
else
loc = new Point(calLoc.x, calLoc.y + size.y);
loc = toDisplay(loc);
mCalendarShell.setLocation(loc);
mCalendarShell.setVisible(true);
}
catch (Exception e) {
mComboControl.setCapture(false);
e.printStackTrace();
// don't really care
}
}
/**
* Adds a calendar listener.
*
* @param listener
* Listener
*/
public void addCalendarListener(ICalendarListener listener) {
checkWidget();
if (!mListeners.contains(listener))
mListeners.add(listener);
}
/**
* Removes a calendar listener.
*
* @param listener
* Listener
*/
public void removeCalendarListener(ICalendarListener listener) {
checkWidget();
mListeners.remove(listener);
}
/**
* Returns the combo box widget.
* <p>
* <font color="red"><b>NOTE:</b> The Combo box has a lot of listeners on
* it, please be "careful" when using it as you may cause unplanned-for
* things to happen.</font>
*
* @return Combo widget
*/
public Combo getCombo() {
checkWidget();
return mCombo;
}
public FlatCalendarCombo getCCombo() {
checkWidget();
return mFlatCombo;
}
private void updateDate() {
setText(DateHelper.getDate(mStartDate, mSettings.getDateFormat()));
}
/**
* Puts focus on the combo box.
*
* @deprecated please use {@link #setFocus()}
*/
public void grabFocus() {
checkWidget();
if (isFlat)
mFlatCombo.setFocus();
else
mCombo.setFocus();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.widgets.Composite#setFocus()
*/
public boolean setFocus() {
checkWidget();
if (this.isFlat) {
return this.getCCombo().getTextControl().setFocus();
}
else {
return this.mCombo.setFocus();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.widgets.Control#forceFocus()
*/
public boolean forceFocus() {
checkWidget();
if (this.isFlat) {
return this.getCCombo().getTextControl().forceFocus();
}
else {
return this.mCombo.forceFocus();
}
}
public void setEnabled(boolean enabled) {
checkWidget();
if (isFlat)
mFlatCombo.setEnabled(enabled);
else
mCombo.setEnabled(enabled);
}
public boolean isEnabled() {
checkWidget();
return isFlat ? mFlatCombo.getEnabled() : mCombo.getEnabled();
}
/**
* Adds a modification listener to the combo box.
*
* @param ml
* ModifyListener
*/
public void addModifyListener(ModifyListener ml) {
checkWidget();
if (isFlat)
mFlatCombo.addModifyListener(ml);
else
mCombo.addModifyListener(ml);
}
/**
* Removes a modification listener from the combo box.
*
* @param ml
* ModifyListener
*/
public void removeModifyListener(ModifyListener ml) {
checkWidget();
if (isFlat)
mFlatCombo.removeModifyListener(ml);
else
mCombo.removeModifyListener(ml);
}
/**
* The date prior to which selection is not allowed.
*
* @return Date
*/
public Calendar getDisallowBeforeDate() {
return mDisallowBeforeDate;
}
/**
* Sets the date prior to which selection is not allowed.
*
* @param disallowBeforeDate
* Date
*/
public void setDisallowBeforeDate(Calendar disallowBeforeDate) {
mDisallowBeforeDate = disallowBeforeDate;
}
/**
* Sets the date prior to which selection is not allowed.
*
* @param disallowBeforeDate
* Date
*/
public void setDisallowBeforeDate(Date disallowBeforeDate) {
Calendar cal = Calendar.getInstance(mSettings.getLocale());
cal.setTime(disallowBeforeDate);
mDisallowBeforeDate = cal;
}
/**
* The date after which selection is not allowed.
*
* @return Date
*/
public Calendar getDisallowAfterDate() {
return mDisallowAfterDate;
}
/**
* Sets the date after which selection is not allowed.
*
* @param disallowAfterDate
* Date
*/
public void setDisallowAfterDate(Calendar disallowAfterDate) {
mDisallowAfterDate = disallowAfterDate;
}
/**
* Sets the date after which selection is not allowed.
*
* @param disallowAfterDate
*/
public void setDisallowAfterDate(Date disallowAfterDate) {
Calendar cal = Calendar.getInstance(mSettings.getLocale());
cal.setTime(disallowAfterDate);
mDisallowAfterDate = cal;
}
/**
* Sets the CalendarCombo that will be the recipient of (end date) date
* range changes as well as date start date that will be used.
*
* @param combo
* CalendarCombo
*/
public void setDependingCombo(CalendarCombo combo) {
mDependingCombo = combo;
}
/**
* Returns the CalendarCombo that is the recipient of (end date) date range
* changes as well as date start date that will be used.
*
* @return CalendarCombo
*/
public CalendarCombo getDependingCombo() {
return mDependingCombo;
}
public void addControlListener(ControlListener listener) {
mComboControl.addControlListener(listener);
}
public void addDragDetectListener(DragDetectListener listener) {
mComboControl.addDragDetectListener(listener);
}
public void addFocusListener(FocusListener listener) {
mComboControl.addFocusListener(listener);
}
public void addHelpListener(HelpListener listener) {
mComboControl.addHelpListener(listener);
}
public void addKeyListener(KeyListener listener) {
mComboControl.addKeyListener(listener);
}
public void addMenuDetectListener(MenuDetectListener listener) {
mComboControl.addMenuDetectListener(listener);
}
public void addMouseListener(MouseListener listener) {
mComboControl.addMouseListener(listener);
}
public void addMouseMoveListener(MouseMoveListener listener) {
mComboControl.addMouseMoveListener(listener);
}
public void addMouseTrackListener(MouseTrackListener listener) {
mComboControl.addMouseTrackListener(listener);
}
public void addMouseWheelListener(MouseWheelListener listener) {
mComboControl.addMouseWheelListener(listener);
}
public void addPaintListener(PaintListener listener) {
mComboControl.addPaintListener(listener);
}
public void addTraverseListener(TraverseListener listener) {
mComboControl.addTraverseListener(listener);
}
public void addDisposeListener(DisposeListener listener) {
mComboControl.addDisposeListener(listener);
}
public void addListener(int eventType, Listener listener) {
mComboControl.addListener(eventType, listener);
}
public void removeControlListener(ControlListener listener) {
mComboControl.removeControlListener(listener);
}
public void removeDragDetectListener(DragDetectListener listener) {
mComboControl.removeDragDetectListener(listener);
}
public void removeFocusListener(FocusListener listener) {
mComboControl.removeFocusListener(listener);
}
public void removeHelpListener(HelpListener listener) {
mComboControl.removeHelpListener(listener);
}
public void removeKeyListener(KeyListener listener) {
mComboControl.removeKeyListener(listener);
}
public void removeMenuDetectListener(MenuDetectListener listener) {
mComboControl.removeMenuDetectListener(listener);
}
public void removeMouseListener(MouseListener listener) {
mComboControl.removeMouseListener(listener);
}
public void removeMouseMoveListener(MouseMoveListener listener) {
mComboControl.removeMouseMoveListener(listener);
}
public void removeMouseTrackListener(MouseTrackListener listener) {
mComboControl.removeMouseTrackListener(listener);
}
public void removeMouseWheelListener(MouseWheelListener listener) {
mComboControl.removeMouseWheelListener(listener);
}
public void removePaintListener(PaintListener listener) {
mComboControl.removePaintListener(listener);
}
public void removeTraverseListener(TraverseListener listener) {
mComboControl.removeTraverseListener(listener);
}
public void notifyListeners(int eventType, Event event) {
mComboControl.notifyListeners(eventType, event);
}
public void removeDisposeListener(DisposeListener listener) {
mComboControl.removeDisposeListener(listener);
}
public void removeListener(int eventType, Listener listener) {
mComboControl.removeListener(eventType, listener);
}
public Composite getActiveComboControl() {
return mComboControl;
}
}