# HG changeset patch
# User Frank Benoit Does not modify the reciever. Returns a FontDescriptor that is equivalent to the reciever, but
+ * has the given style bits, in addition to any styles the reciever already has. Does not modify the reciever. Returns a new FontDescriptor that is equivalent to the reciever, but
+ * has the given height. Does not modify the reciever. Returns a FontDescriptor that is equivalent to the reciever, but whose height
+ * is larger by the given number of points. Does not modify the reciever.
+ * A font registry owns all of the font objects registered
+ * with it, and automatically disposes of them when the DWT Display
+ * that creates the fonts is disposed. Because of this, clients do
+ * not need to (indeed, must not attempt to) dispose of font
+ * objects themselves.
+ *
+ * A special constructor is provided for populating a font registry
+ * from a property files using the standard Java resource bundle mechanism.
+ *
+ * Methods are provided for registering listeners that will be kept
+ * apprised of changes to list of registed fonts.
+ *
+ * Clients may instantiate this class (it was not designed to be subclassed).
+ *
+ * There must be an DWT Display created in the current
+ * thread before calling this method.
+ *
+ * There must be an DWT Display created in the current
+ * thread before calling this method.
+ *
+ * The OS name (retrieved using
+ * For example, on the Windows 2000 operating system the location string
+ *
+ * If no appropriate OS-specific resource bundle is found, the
+ * process is repeated using the location as the base bundle name.
+ *
+ * The property file contains entries that look like this:
+ * null
. If this
* is not the case, some kind of unchecked exception is thrown.
diff -r 1a6747be662d -r 8a302fdb4140 dwtx/jface/resource/ArrayFontDescriptor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/resource/ArrayFontDescriptor.d Fri Mar 28 23:32:40 2008 +0100
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit String
,
+ * value type: FontRecord
.
+ */
+ private Map!(String,FontRecord) stringToFontRecord;
+
+ /**
+ * Table of known font data, keyed by symbolic font name
+ * (key type: String
,
+ * value type: dwt.graphics.FontData[]
).
+ */
+ private Map!(String,FontData[]) stringToFontData;
+
+ /**
+ * Collection of Fonts that are now stale to be disposed
+ * when it is safe to do so (i.e. on shutdown).
+ * @see List
+ */
+ private Seq!(Font) staleFonts;
+
+ /**
+ * Runnable that cleans up the manager on disposal of the display.
+ */
+ protected Runnable displayRunnable;
+
+ /**
+ * Creates an empty font registry.
+ * System.getProperty("os.name")
)
+ * is converted to lowercase, purged of whitespace, and appended
+ * as suffix (separated by an underscore '_'
) to the given
+ * location string to yield the base name of a resource bundle
+ * acceptable to ResourceBundle.getBundle
.
+ * The standard Java resource bundle mechanism is then used to locate
+ * and open the appropriate properties file, taking into account
+ * locale specific variations.
+ * "com.example.myapp.Fonts"
yields the base name
+ * "com.example.myapp.Fonts_windows2000"
. For the US English locale,
+ * this further elaborates to the resource bundle name
+ * "com.example.myapp.Fonts_windows2000_en_us"
.
+ *
+ * textfont.0=MS Sans Serif-regular-10
+ * textfont.1=Times New Roman-regular-10
+ *
+ * titlefont.0=MS Sans Serif-regular-12
+ * titlefont.1=Times New Roman-regular-12
+ *
+ * Each entry maps a symbolic font names (the font registry keys) with
+ * a ".
suffix to standard font names
+ * on the right. The suffix indicated order of preference:
+ * ".0
" indicates the first choice,
+ * ".1
" indicates the second choice, and so on.
+ *
+ * FontRegistry registry = new FontRegistry("com.example.myapp.fonts"); + * Font font = registry.get("textfont"); + * control.setFont(font); + * ... + *+ * + * @param location the name of the resource bundle + * @param loader the ClassLoader to use to find the resource bundle + * @exception MissingResourceException if the resource bundle cannot be found + * @since 2.1 + */ + public this(String location, /+ClassLoader+/Object loader){ + initInstance(); + Display display = Display.getCurrent(); + Assert.isNotNull(display); + // FIXE: need to respect loader + //readResourceBundle(location, loader); + readResourceBundle(location); + + hookDisplayDispose(display); + } + + private void initInstance(){ + displayRunnable = new class Runnable { + public void run() { + clearCaches(); + } + }; + stringToFontRecord = new HashMap!(String,FontRecord); + //stringToFontRecord.capacity(7); + + stringToFontData = new HashMap!(String,FontData[]); + //stringToFontData.capacity(7); + + staleFonts = new ArraySeq!(Font); + } + + /** + * Load the FontRegistry using the ClassLoader from the PlatformUI + * plug-in + * @param location the location to read the resource bundle from + * @throws MissingResourceException Thrown if a resource is missing + */ + public this(String location) { + // FIXE: + // this(location, WorkbenchPlugin.getDefault().getDescriptor().getPluginClassLoader()); + this(location, null); + } + + /** + * Read the resource bundle at location. Look for a file with the + * extension _os_ws first, then _os then just the name. + * @param location - String - the location of the file. + */ + + private void readResourceBundle(String location) { + String osname = System.getProperty("os.name").trim(); //$NON-NLS-1$ + String wsname = DWT.getPlatform(); + osname = StringConverter.removeWhiteSpaces(osname).toLowerCase(); + wsname = StringConverter.removeWhiteSpaces(wsname).toLowerCase(); + String OSLocation = location; + String WSLocation = location; + ResourceBundle bundle = null; + if (osname !is null) { + OSLocation = location ~ "_" ~ osname; //$NON-NLS-1$ + if (wsname !is null) { + WSLocation = OSLocation ~ "_" ~ wsname; //$NON-NLS-1$ + } + } + + try { + bundle = ResourceBundle.getBundle(WSLocation); + readResourceBundle(bundle, WSLocation); + } catch (MissingResourceException wsException) { + try { + bundle = ResourceBundle.getBundle(OSLocation); + readResourceBundle(bundle, WSLocation); + } catch (MissingResourceException osException) { + if (location !is OSLocation) { + bundle = ResourceBundle.getBundle(location); + readResourceBundle(bundle, WSLocation); + } else { + throw osException; + } + } + } + } + + /** + * Creates an empty font registry. + * + * @param display the Display + */ + public this(Display display) { + this(display, true); + } + + /** + * Creates an empty font registry. + * + * @param display + * the
Display
+ * @param cleanOnDisplayDisposal
+ * whether all fonts allocated by this FontRegistry
+ * should be disposed when the display is disposed
+ * @since 3.1
+ */
+ public this(Display display, bool cleanOnDisplayDisposal) {
+ initInstance();
+ Assert.isNotNull(display);
+ if (cleanOnDisplayDisposal) {
+ hookDisplayDispose(display);
+ }
+ }
+
+ /**
+ * Find the first valid fontData in the provided list. If none are valid
+ * return the first one regardless. If the list is empty return null. Return
+ * null
if one cannot be found.
+ *
+ * @param fonts the font list
+ * @param display the display used
+ * @return the font data of the like describe above
+ *
+ * @deprecated use bestDataArray in order to support Motif multiple entry
+ * fonts.
+ */
+ public FontData bestData(FontData[] fonts, Display display) {
+ for (int i = 0; i < fonts.length; i++) {
+ FontData fd = fonts[i];
+
+ if (fd is null) {
+ break;
+ }
+
+ FontData[] fixedFonts = display.getFontList(fd.getName(), false);
+ if (isFixedFont(fixedFonts, fd)) {
+ return fd;
+ }
+
+ FontData[] scalableFonts = display.getFontList(fd.getName(), true);
+ if (scalableFonts.length > 0) {
+ return fd;
+ }
+ }
+
+ //None of the provided datas are valid. Return the
+ //first one as it is at least the first choice.
+ if (fonts.length > 0) {
+ return fonts[0];
+ }
+
+ //Nothing specified
+ return null;
+ }
+
+ /**
+ * Find the first valid fontData in the provided list.
+ * If none are valid return the first one regardless.
+ * If the list is empty return null
.
+ *
+ * @param fonts list of fonts
+ * @param display the display
+ * @return font data like described above
+ * @deprecated use filterData in order to preserve
+ * multiple entry fonts on Motif
+ */
+ public FontData[] bestDataArray(FontData[] fonts, Display display) {
+
+ FontData bestData = bestData(fonts, display);
+ if (bestData is null) {
+ return null;
+ }
+
+ FontData[] datas = new FontData[1];
+ datas[0] = bestData;
+ return datas;
+ }
+
+ /**
+ * Removes from the list all fonts that do not exist in this system.
+ * If none are valid, return the first irregardless. If the list is
+ * empty return null
.
+ *
+ * @param fonts the fonts to check
+ * @param display the display to check against
+ * @return the list of fonts that have been found on this system
+ * @since 3.1
+ */
+ public FontData [] filterData(FontData [] fonts, Display display) {
+ ArraySeq!(FontData) good = new ArraySeq!(FontData);
+ good.capacity(fonts.length);
+ for (int i = 0; i < fonts.length; i++) {
+ FontData fd = fonts[i];
+
+ if (fd is null) {
+ continue;
+ }
+
+ FontData[] fixedFonts = display.getFontList(fd.getName(), false);
+ if (isFixedFont(fixedFonts, fd)) {
+ good.append(fd);
+ }
+
+ FontData[] scalableFonts = display.getFontList(fd.getName(), true);
+ if (scalableFonts.length > 0) {
+ good.append(fd);
+ }
+ }
+
+
+ //None of the provided datas are valid. Return the
+ //first one as it is at least the first choice.
+ if (good.drained() && fonts.length > 0) {
+ good.append(fonts[0]);
+ }
+ else if (fonts.length is 0) {
+ return null;
+ }
+
+ return good.toArray();
+ }
+
+
+ /**
+ * Creates a new font with the given font datas or null
+ * if there is no data.
+ * @return FontRecord for the new Font or null
.
+ */
+ private FontRecord createFont(String symbolicName, FontData[] fonts) {
+ Display display = Display.getCurrent();
+ if (display is null) {
+ return null;
+ }
+
+ FontData[] validData = filterData(fonts, display);
+ if (validData.length is 0) {
+ //Nothing specified
+ return null;
+ }
+
+ //Do not fire the update from creation as it is not a property change
+ put(symbolicName, validData, false);
+ Font newFont = new Font(display, validData);
+ return new FontRecord(newFont, validData);
+ }
+
+ /**
+ * Calculates the default font and returns the result.
+ * This method creates a font that must be disposed.
+ */
+ Font calculateDefaultFont() {
+ Display current = Display.getCurrent();
+ if (current is null) {
+ Shell shell = new Shell();
+ Font font = new Font(null, shell.getFont().getFontData());
+ shell.dispose();
+ return font;
+ }
+ return new Font(current, current.getSystemFont().getFontData());
+ }
+
+ /**
+ * Returns the default font data. Creates it if necessary.
+ * @return Font
+ */
+ public Font defaultFont() {
+ return defaultFontRecord().getBaseFont();
+ }
+
+ /**
+ * Returns the font descriptor for the font with the given symbolic
+ * font name. Returns the default font if there is no special value
+ * associated with that name
+ *
+ * @param symbolicName symbolic font name
+ * @return the font descriptor (never null)
+ *
+ * @since 3.3
+ */
+ public FontDescriptor getDescriptor(String symbolicName) {
+ Assert.isTrue(symbolicName.length > 0);
+ return FontDescriptor.createFrom(getFontData(symbolicName));
+ }
+
+
+
+ /**
+ * Returns the default font record.
+ */
+ private FontRecord defaultFontRecord() {
+
+ FontRecord record = cast(FontRecord) stringToFontRecord
+ .get(JFaceResources.DEFAULT_FONT);
+ if (record is null) {
+ Font defaultFont = calculateDefaultFont();
+ record = createFont(JFaceResources.DEFAULT_FONT, defaultFont
+ .getFontData());
+ defaultFont.dispose();
+ stringToFontRecord.add(JFaceResources.DEFAULT_FONT, record);
+ }
+ return record;
+ }
+
+ /**
+ * Returns the default font data. Creates it if necessary.
+ */
+ private FontData[] defaultFontData() {
+ return defaultFontRecord().baseData;
+ }
+
+ /**
+ * Returns the font data associated with the given symbolic font name.
+ * Returns the default font data if there is no special value associated
+ * with that name.
+ *
+ * @param symbolicName symbolic font name
+ * @return the font
+ */
+ public FontData[] getFontData(String symbolicName) {
+
+ Assert.isTrue(symbolicName.length > 0);
+ auto result = stringToFontData.get(symbolicName);
+ if (result.length is 0) {
+ return defaultFontData();
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the font associated with the given symbolic font name.
+ * Returns the default font if there is no special value associated
+ * with that name.
+ *
+ * @param symbolicName symbolic font name
+ * @return the font
+ */
+ public Font get(String symbolicName) {
+
+ return getFontRecord(symbolicName).getBaseFont();
+ }
+
+ /**
+ * Returns the bold font associated with the given symbolic font name.
+ * Returns the bolded default font if there is no special value associated
+ * with that name.
+ *
+ * @param symbolicName symbolic font name
+ * @return the font
+ * @since 3.0
+ */
+ public Font getBold(String symbolicName) {
+
+ return getFontRecord(symbolicName).getBoldFont();
+ }
+
+ /**
+ * Returns the italic font associated with the given symbolic font name.
+ * Returns the italic default font if there is no special value associated
+ * with that name.
+ *
+ * @param symbolicName symbolic font name
+ * @return the font
+ * @since 3.0
+ */
+ public Font getItalic(String symbolicName) {
+
+ return getFontRecord(symbolicName).getItalicFont();
+ }
+
+ /**
+ * Return the font record for the key.
+ * @param symbolicName The key for the record.
+ * @return FontRecird
+ */
+ private FontRecord getFontRecord(String symbolicName) {
+ Assert.isNotNull(symbolicName);
+ Object result1 = stringToFontRecord.get(symbolicName);
+ if (result1 !is null) {
+ return cast(FontRecord) result1;
+ }
+
+ auto result = stringToFontData.get(symbolicName);
+
+ FontRecord fontRecord;
+
+ if (result is null) {
+ fontRecord = defaultFontRecord();
+ } else {
+ fontRecord = createFont(symbolicName, result);
+ }
+
+ if (fontRecord is null) {
+ fontRecord = defaultFontRecord();
+ }
+
+ stringToFontRecord.add(symbolicName, fontRecord);
+ return fontRecord;
+
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.resource.ResourceRegistry#getKeySet()
+ */
+ public SetView!(String) getKeySet() {
+ auto res = new HashSet!(String);
+ foreach( k, v; stringToFontData ){
+ res.add( k );
+ }
+ return res;
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.resource.ResourceRegistry#hasValueFor(java.lang.String)
+ */
+ public bool hasValueFor(String fontKey) {
+ return stringToFontData.containsKey(fontKey);
+ }
+
+ /* (non-Javadoc)
+ * @see dwtx.jface.resource.ResourceRegistry#clearCaches()
+ */
+ protected void clearCaches() {
+ foreach( k,v; stringToFontRecord ){
+ v.dispose();
+ }
+
+ disposeFonts(staleFonts);
+ stringToFontRecord.clear();
+ staleFonts.clear();
+ }
+
+ /**
+ * Dispose of all of the fonts in this iterator.
+ * @param iterator over Collection of Font
+ */
+ private void disposeFonts( Seq!(Font) list ) {
+ foreach( fnt; list ){
+ fnt.dispose();
+ }
+ }
+
+ /**
+ * Hook a dispose listener on the DWT display.
+ */
+ private void hookDisplayDispose(Display display) {
+ display.disposeExec(displayRunnable);
+ }
+
+ /**
+ * Checks whether the given font is in the list of fixed fonts.
+ */
+ private bool isFixedFont(FontData[] fixedFonts, FontData fd) {
+ // Can't use FontData.equals() since some values aren't
+ // set if a fontdata isn't used.
+ int height = fd.getHeight();
+ String name = fd.getName();
+ for (int i = 0; i < fixedFonts.length; i++) {
+ FontData fixed = fixedFonts[i];
+ if (fixed.getHeight() is height && fixed.getName().equals(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Converts a String into a FontData object.
+ */
+ private FontData makeFontData(String value) {
+ try {
+ return StringConverter.asFontData(value.trim());
+ } catch (DataFormatException e) {
+ throw new MissingResourceException(
+ "Wrong font data format. Value is: \"" ~ value ~ "\"", this.classinfo.name, value); //$NON-NLS-2$//$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Adds (or replaces) a font to this font registry under the given
+ * symbolic name.
+ * + * A property change event is reported whenever the mapping from + * a symbolic name to a font changes. The source of the event is + * this registry; the property name is the symbolic font name. + *
+ * + * @param symbolicName the symbolic font name + * @param fontData an Array of FontData + */ + public void put(String symbolicName, FontData[] fontData) { + put(symbolicName, fontData, true); + } + + /** + * Adds (or replaces) a font to this font registry under the given + * symbolic name. + *+ * A property change event is reported whenever the mapping from + * a symbolic name to a font changes. The source of the event is + * this registry; the property name is the symbolic font name. + *
+ * + * @param symbolicName the symbolic font name + * @param fontData an Array of FontData + * @param update - fire a font mapping changed if true. False + * if this method is called from the get method as no setting + * has changed. + */ + private void put(String symbolicName, FontData[] fontData, bool update) { + + Assert.isNotNull(symbolicName); + Assert.isTrue(fontData.length > 0 ); + + FontData[] existing = stringToFontData.get(symbolicName); + if (ArrayEquals(existing, fontData)) { + return; + } + + FontRecord oldFont = stringToFontRecord.get(symbolicName); + stringToFontRecord.removeKey(symbolicName); + stringToFontData.add(symbolicName, fontData); + if (update) { + fireMappingChanged(symbolicName, new ArrayWrapperT!(FontData)(existing), new ArrayWrapperT!(FontData)(fontData)); + } + + if (oldFont !is null) { + oldFont.addAllocatedFontsToStale(defaultFontRecord().getBaseFont()); + } + } + + /** + * Reads the resource bundle. This puts FontData[] objects + * in the mapping table. These will lazily be turned into + * real Font objects when requested. + */ + private void readResourceBundle(ResourceBundle bundle, String bundleName) { + foreach( key; bundle.getKeys() ){ + int pos = key.lastIndexOf('.'); + if (pos is -1) { + stringToFontData.add(key, [ makeFontData(bundle.getString(key)) ]); + } else { + String name = key.substring(0, pos); + int i = 0; + try { + i = tango.text.convert.Integer.toInt(key.substring(pos + 1)); + } catch (IllegalArgumentException e) { + //Panic the file can not be parsed. + throw new MissingResourceException( + "Wrong key format ", bundleName, key); //$NON-NLS-1$ + } + FontData[] elements = stringToFontData.get(name); + if (elements is null) { + elements = new FontData[8]; + stringToFontData.add(name, elements); + } + if (i > elements.length) { + FontData[] na = new FontData[i + 8]; + System.arraycopy(elements, 0, na, 0, elements.length); + elements = na; + stringToFontData.add(name, elements); + } + elements[i] = makeFontData(bundle.getString(key)); + } + } + } + + /** + * Returns the font descriptor for the JFace default font. + * + * @return the font descriptor for the JFace default font + * @since 3.3 + */ + public FontDescriptor defaultFontDescriptor() { + return FontDescriptor.createFrom(defaultFontData()); + } +} diff -r 1a6747be662d -r 8a302fdb4140 dwtx/jface/resource/JFaceResources.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/resource/JFaceResources.d Fri Mar 28 23:32:40 2008 +0100 @@ -0,0 +1,589 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit+ * All methods declared on this class are static. This class cannot be + * instantiated. + *
+ *+ * The following global state is also maintained by this class: + *
"dwtx.jface.bannerfont"
).
+ */
+ public static final String BANNER_FONT = "dwtx.jface.bannerfont"; //$NON-NLS-1$
+
+ /**
+ * The JFace resource bundle; eagerly initialized.
+ */
+ private static final ResourceBundle bundle = ResourceBundle
+ .getBundle("dwtx.jface.messages"); //$NON-NLS-1$
+
+ /**
+ * The JFace color registry; null
until lazily initialized or
+ * explicitly set.
+ */
+ private static ColorRegistry colorRegistry;
+
+ /**
+ * The symbolic font name for the standard font (value
+ * "dwtx.jface.defaultfont"
).
+ */
+ public static final String DEFAULT_FONT = "dwtx.jface.defaultfont"; //$NON-NLS-1$
+
+ /**
+ * The symbolic font name for the dialog font (value
+ * "dwtx.jface.dialogfont"
).
+ */
+ public static final String DIALOG_FONT = "dwtx.jface.dialogfont"; //$NON-NLS-1$
+
+ /**
+ * The JFace font registry; null
until lazily initialized or
+ * explicitly set.
+ */
+ private static FontRegistry fontRegistry = null;
+
+ /**
+ * The symbolic font name for the header font (value
+ * "dwtx.jface.headerfont"
).
+ */
+ public static final String HEADER_FONT = "dwtx.jface.headerfont"; //$NON-NLS-1$
+
+ /**
+ * The JFace image registry; null
until lazily initialized.
+ */
+ private static ImageRegistry imageRegistry = null;
+
+ /**
+ * The symbolic font name for the text font (value
+ * "dwtx.jface.textfont"
).
+ */
+ public static final String TEXT_FONT = "dwtx.jface.textfont"; //$NON-NLS-1$
+
+ /**
+ * The symbolic font name for the viewer font (value
+ * "dwtx.jface.viewerfont"
).
+ *
+ * @deprecated This font is not in use
+ */
+ public static final String VIEWER_FONT = "dwtx.jface.viewerfont"; //$NON-NLS-1$
+
+ /**
+ * The symbolic font name for the window font (value
+ * "dwtx.jface.windowfont"
).
+ *
+ * @deprecated This font is not in use
+ */
+ public static final String WINDOW_FONT = "dwtx.jface.windowfont"; //$NON-NLS-1$
+
+ /**
+ * Returns the formatted message for the given key in JFace's resource
+ * bundle.
+ *
+ * @param key
+ * the resource name
+ * @param args
+ * the message arguments
+ * @return the string
+ */
+ public static String format(String key, Object[] args) {
+ return MessageFormat.format(getString(key), args);
+ }
+
+ /**
+ * Returns the JFace's banner font. Convenience method equivalent to
+ *
+ * + * JFaceResources.getFontRegistry().get(JFaceResources.BANNER_FONT) + *+ * + * @return the font + */ + public static Font getBannerFont() { + return getFontRegistry().get(BANNER_FONT); + } + + /** + * Returns the resource bundle for JFace itself. The resouble bundle is + * obtained from + *
ResourceBundle.getBundle("dwtx.jface.jface_nls")
.
+ * + * Note that several static convenience methods are also provided on this + * class for directly accessing resources in this bundle. + *
+ * + * @return the resource bundle + */ + public static ResourceBundle getBundle() { + return bundle; + } + + /** + * Returns the color registry for JFace itself. + *
+ *
+ * @return the ColorRegistry
.
+ * @since 3.0
+ */
+ public static ColorRegistry getColorRegistry() {
+ if (colorRegistry is null) {
+ colorRegistry = new ColorRegistry();
+ }
+ return colorRegistry;
+ }
+
+ /**
+ * Returns the global resource manager for the given display
+ *
+ * @since 3.1
+ *
+ * @param toQuery
+ * display to query
+ * @return the global resource manager for the given display
+ */
+ public static ResourceManager getResources(final Display toQuery) {
+ ResourceManager reg = (ResourceManager) registries.get(toQuery);
+
+ if (reg is null) {
+ final DeviceResourceManager mgr = new DeviceResourceManager(toQuery);
+ reg = mgr;
+ registries.put(toQuery, reg);
+ toQuery.disposeExec(new Runnable() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ mgr.dispose();
+ registries.remove(toQuery);
+ }
+ });
+ }
+
+ return reg;
+ }
+
+ /**
+ * Returns the ResourceManager for the current display. May only be called
+ * from a UI thread.
+ *
+ * @since 3.1
+ *
+ * @return the global ResourceManager for the current display
+ */
+ public static ResourceManager getResources() {
+ return getResources(Display.getCurrent());
+ }
+
+ /**
+ * Returns JFace's standard font. Convenience method equivalent to
+ *
+ *
+ * JFaceResources.getFontRegistry().get(JFaceResources.DEFAULT_FONT) + *+ * + * @return the font + */ + public static Font getDefaultFont() { + return getFontRegistry().defaultFont(); + } + + /** + * Returns the descriptor for JFace's standard font. Convenience method + * equivalent to + * + *
+ * JFaceResources.getFontRegistry().getDescriptor(JFaceResources.DEFAULT_FONT) + *+ * + * @return the font + * @since 3.3 + */ + public static FontDescriptor getDefaultFontDescriptor() { + return getFontRegistry().defaultFontDescriptor(); + } + + /** + * Returns the JFace's dialog font. Convenience method equivalent to + * + *
+ * JFaceResources.getFontRegistry().get(JFaceResources.DIALOG_FONT) + *+ * + * @return the font + */ + public static Font getDialogFont() { + return getFontRegistry().get(DIALOG_FONT); + } + + /** + * Returns the descriptor for JFace's dialog font. Convenience method + * equivalent to + * + *
+ * JFaceResources.getFontRegistry().getDescriptor(JFaceResources.DIALOG_FONT) + *+ * + * @return the font + * @since 3.3 + */ + public static FontDescriptor getDialogFontDescriptor() { + return getFontRegistry().getDescriptor(DIALOG_FONT); + } + + /** + * Returns the font in JFace's font registry with the given symbolic font + * name. Convenience method equivalent to + * + *
+ * JFaceResources.getFontRegistry().get(symbolicName) + *+ * + * If an error occurs, return the default font. + * + * @param symbolicName + * the symbolic font name + * @return the font + */ + public static Font getFont(String symbolicName) { + return getFontRegistry().get(symbolicName); + } + + /** + * Returns the font descriptor for in JFace's font registry with the given + * symbolic name. Convenience method equivalent to + * + *
+ * JFaceResources.getFontRegistry().getDescriptor(symbolicName) + *+ * + * If an error occurs, return the default font. + * + * @param symbolicName + * the symbolic font name + * @return the font descriptor (never null) + * @since 3.3 + */ + public static FontDescriptor getFontDescriptor(String symbolicName) { + return getFontRegistry().getDescriptor(symbolicName); + } + + /** + * Returns the font registry for JFace itself. If the value has not been + * established by an earlier call to
setFontRegistry
, is it
+ * initialized to
+ * new FontRegistry("dwtx.jface.resource.jfacefonts")
.
+ * + * Note that several static convenience methods are also provided on this + * class for directly accessing JFace's standard fonts. + *
+ * + * @return the JFace font registry + */ + public static FontRegistry getFontRegistry() { + if (fontRegistry is null) { + fontRegistry = new FontRegistry( + "dwtx.jface.resource.jfacefonts"); //$NON-NLS-1$ + } + return fontRegistry; + } + + /** + * Returns the JFace's header font. Convenience method equivalent to + * + *+ * JFaceResources.getFontRegistry().get(JFaceResources.HEADER_FONT) + *+ * + * @return the font + */ + public static Font getHeaderFont() { + return getFontRegistry().get(HEADER_FONT); + } + + /** + * Returns the descriptor for JFace's header font. Convenience method + * equivalent to + * + *
+ * JFaceResources.getFontRegistry().get(JFaceResources.HEADER_FONT) + *+ * + * @return the font descriptor (never null) + * @since 3.3 + */ + public static FontDescriptor getHeaderFontDescriptor() { + return getFontRegistry().getDescriptor(HEADER_FONT); + } + + /** + * Returns the image in JFace's image registry with the given key, or + *
null
if none. Convenience method equivalent to
+ *
+ * + * JFaceResources.getImageRegistry().get(key) + *+ * + * @param key + * the key + * @return the image, or
null
if none
+ */
+ public static Image getImage(String key) {
+ return getImageRegistry().get(key);
+ }
+
+ /**
+ * Returns the image registry for JFace itself.
+ *
+ * Note that the static convenience method getImage
is also
+ * provided on this class.
+ *
declareImage
method.
+ *
+ * @param bundle
+ * the {@link Bundle} or null
of the Bundle cannot
+ * be found
+ * @param key
+ * the symbolic name of the image
+ * @param path
+ * the path of the image file relative to the base of the
+ * workbench plug-ins install directory
+ * @param fallback
+ * the {@link Class} where the fallback implementation of the
+ * image is relative to
+ * @param fallbackPath
+ * the path relative to the fallback {@link Class}
+ *
+ */
+ private static final void declareImage(Object bundle, String key,
+ String path, Class fallback, String fallbackPath) {
+
+
+ ImageDescriptor descriptor = null;
+
+ if (bundle !is null) {
+//FIXME
+// URL url = FileLocator.find((Bundle) bundle, new Path(path), null);
+// if (url !is null)
+// descriptor = ImageDescriptor.createFromURL(url);
+ }
+
+ // If we failed then load from the backup file
+ if (descriptor is null)
+ descriptor = ImageDescriptor.createFromFile(fallback, fallbackPath);
+
+ imageRegistry.put(key, descriptor);
+ }
+
+ /**
+ * Returns the resource object with the given key in JFace's resource
+ * bundle. If there isn't any value under the given key, the key is
+ * returned.
+ *
+ * @param key
+ * the resource name
+ * @return the string
+ */
+ public static String getString(String key) {
+ try {
+ return bundle.getString(key);
+ } catch (MissingResourceException e) {
+ return key;
+ }
+ }
+
+ /**
+ * Returns a list of string values corresponding to the given list of keys.
+ * The lookup is done with getString
. The values are in the
+ * same order as the keys.
+ *
+ * @param keys
+ * a list of keys
+ * @return a list of corresponding string values
+ */
+ public static String[] getStrings(String[] keys) {
+ Assert.isNotNull(keys);
+ int length = keys.length;
+ String[] result = new String[length];
+ for (int i = 0; i < length; i++) {
+ result[i] = getString(keys[i]);
+ }
+ return result;
+ }
+
+ /**
+ * Returns JFace's text font. Convenience method equivalent to
+ *
+ * + * JFaceResources.getFontRegistry().get(JFaceResources.TEXT_FONT) + *+ * + * @return the font + */ + public static Font getTextFont() { + return getFontRegistry().get(TEXT_FONT); + } + + /** + * Returns the descriptor for JFace's text font. Convenience method + * equivalent to + * + *
+ * JFaceResources.getFontRegistry().getDescriptor(JFaceResources.TEXT_FONT) + *+ * + * @return the font descriptor (never null) + * @since 3.3 + */ + public static FontDescriptor getTextFontDescriptor() { + return getFontRegistry().getDescriptor(TEXT_FONT); + } + + /** + * Returns JFace's viewer font. Convenience method equivalent to + * + *
+ * JFaceResources.getFontRegistry().get(JFaceResources.VIEWER_FONT) + *+ * + * @return the font + * @deprecated This font is not in use + */ + public static Font getViewerFont() { + return getFontRegistry().get(VIEWER_FONT); + } + + /** + * Sets JFace's font registry to the given value. This method may only be + * called once; the call must occur before + *
JFaceResources.getFontRegistry
is invoked (either directly
+ * or indirectly).
+ *
+ * @param registry
+ * a font registry
+ */
+ public static void setFontRegistry(FontRegistry registry) {
+ Assert.isTrue(fontRegistry is null,
+ "Font registry can only be set once."); //$NON-NLS-1$
+ fontRegistry = registry;
+ }
+
+ /*
+ * (non-Javadoc) Declare a private constructor to block instantiation.
+ */
+ private JFaceResources() {
+ // no-op
+ }
+}
+++/
\ No newline at end of file
diff -r 1a6747be662d -r 8a302fdb4140 dwtx/jface/resource/ResourceRegistry.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/resource/ResourceRegistry.d Fri Mar 28 23:32:40 2008 +0100
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit true
if there is a value for this key
+ */
+ public abstract bool hasValueFor(String key);
+
+ /**
+ * Fires a PropertyChangeEvent
.
+ *
+ * @param name the name of the symbolic value that is changing.
+ * @param oldValue the old value.
+ * @param newValue the new value.
+ */
+ protected void fireMappingChanged(String name, Object oldValue,
+ Object newValue) {
+ Object[] myListeners = getListeners();
+ if (myListeners.length > 0) {
+ PropertyChangeEvent event = new PropertyChangeEvent(this, name,
+ oldValue, newValue);
+ for (int i = 0; i < myListeners.length; ++i) {
+ try {
+ (cast(IPropertyChangeListener) myListeners[i])
+ .propertyChange(event);
+ } catch (Exception e) {
+ // TODO: how to log?
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes the given listener from this registry. Has no affect if the
+ * listener is not registered.
+ *
+ * @param listener a property change listener
+ */
+ public void removeListener(IPropertyChangeListener listener) {
+ removeListenerObject(cast(Object)listener);
+ }
+}
diff -r 1a6747be662d -r 8a302fdb4140 dwtx/jface/resource/StringConverter.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/resource/StringConverter.d Fri Mar 28 23:32:40 2008 +0100
@@ -0,0 +1,889 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit bool
int
long
float
double
dwt.graphics.Point
dwt.graphics.Rectangle
dwt.graphics.RGB
dwt.graphics.FontData
+ * All methods declared on this class are static. This + * class cannot be instantiated. + *
+ */ +public class StringConverter { + + /** + * Internal font style constant for regular fonts. + */ + private static const String REGULAR = "regular"; //$NON-NLS-1$ + + /** + * Internal font style constant for bold fonts. + */ + private static const String BOLD = "bold"; //$NON-NLS-1$ + + /** + * Internal font style constant for italic fonts. + */ + private static const String ITALIC = "italic"; //$NON-NLS-1$ + + /** + * Internal font style constant for bold italic fonts. + */ + private static const String BOLD_ITALIC = "bold italic"; //$NON-NLS-1$ + + /** + * Internal constant for the separator character used in + * font specifications. + */ + private static const char SEPARATOR = '-'; + + /** + * Internal constant for the seperator character used in font list + * specifications. + */ + private static const String FONT_SEPARATOR = ";"; //$NON-NLS-1$ + + /* (non-Javadoc) + * Declare a private constructor to block instantiation. + */ + private this() { + //no-op + } + + /** + * Breaks out space-separated words into an array of words. + * For example:"no comment"
into an array
+ * a[0]="no"
and a[1]= "comment"
.
+ *
+ * @param value the string to be converted
+ * @return the list of words
+ * @throws DataFormatException thrown if request string could not seperated
+ */
+ public static String[] asArray(String value) {
+ ArraySeq!(String) list = new ArraySeq!(String);
+ foreach ( s; tango.text.Util.delimit( value, " \t\n\r\f" )) {
+ list.append(s);
+ }
+ return list.toArray();
+ }
+
+ /**
+ /**
+ * Breaks out space-separated words into an array of words.
+ * For example: "no comment"
into an array
+ * a[0]="no"
and a[1]= "comment"
.
+ * Returns the given default value if the value cannot be parsed.
+ *
+ * @param value the string to be converted
+ * @param dflt the default value
+ * @return the list of words, or the default value
+ */
+ public static String[] asArray(String value, String[] dflt) {
+ try {
+ return asArray(value);
+ } catch (DataFormatException e) {
+ return dflt;
+ }
+ }
+
+ /**
+ * Converts the given value into a bool.
+ * This method fails if the value does not represent a bool.
+ *
+ * Valid representations of true
include the strings
+ * "t
", "true
", or equivalent in mixed
+ * or upper case.
+ * Similarly, valid representations of false
include the strings
+ * "f
", "false
", or equivalent in mixed
+ * or upper case.
+ *
+ * A valid font data representation is a string of the form
+ *
where
+ *
is the name of a font,
+ *
is a font style (one of
+ * "regular"
, "bold"
,
+ * "italic"
, or "bold italic"
)
+ * and
is an integer representing the
+ * font height. Example: Times New Roman-bold-36
.
+ *
+ * A valid point representation is a string of the form
+ *
where
+ *
and
+ * are valid ints.
+ *
+ * A valid rectangle representation is a string of the form
+ *
+ * where
,
,
+ *
, and
+ * are valid ints.
+ *
+ * A valid RGB color value representation is a string of the form
+ *
,
,
are valid ints.
+ *
String.valueOf(value)
.
+ *
+ * @param value the double value
+ * @return the string representing the given double
+ */
+ public static String asString(double value) {
+ return tango.text.convert.Float.toString(value);
+ }
+
+ /**
+ * Converts the given float value to a string.
+ * Equivalent to String.valueOf(value)
.
+ *
+ * @param value the float value
+ * @return the string representing the given float
+ */
+ public static String asString(float value) {
+ return tango.text.convert.Float.toString(value);
+ }
+
+ /**
+ * Converts the given int value to a string.
+ * Equivalent to String.valueOf(value)
.
+ *
+ * @param value the int value
+ * @return the string representing the given int
+ */
+ public static String asString(int value) {
+ return tango.text.convert.Integer.toString(value);
+ }
+
+ /**
+ * Converts the given long value to a string.
+ * Equivalent to String.valueOf(value)
.
+ *
+ * @param value the long value
+ * @return the string representing the given long
+ */
+ public static String asString(long value) {
+ return tango.text.convert.Integer.toString(value);
+ }
+
+// /**
+// * Converts the given bool object to a string.
+// * Equivalent to String.valueOf(value.booleanValue())
.
+// *
+// * @param value the bool object
+// * @return the string representing the given bool value
+// */
+// public static String asString(Boolean value) {
+// Assert.isNotNull(value);
+// return String.valueOf(value.booleanValue());
+// }
+//
+// /**
+// * Converts the given double object to a string.
+// * Equivalent to String.valueOf(value.doubleValue())
.
+// *
+// * @param value the double object
+// * @return the string representing the given double value
+// */
+// public static String asString(Double value) {
+// Assert.isNotNull(value);
+// return String.valueOf(value.doubleValue());
+// }
+//
+// /**
+// * Converts the given float object to a string.
+// * Equivalent to String.valueOf(value.floatValue())
.
+// *
+// * @param value the float object
+// * @return the string representing the given float value
+// */
+// public static String asString(Float value) {
+// Assert.isNotNull(value);
+// return String.valueOf(value.floatValue());
+// }
+//
+// /**
+// * Converts the given integer object to a string.
+// * Equivalent to String.valueOf(value.intValue())
.
+// *
+// * @param value the integer object
+// * @return the string representing the given integer value
+// */
+// public static String asString(Integer value) {
+// Assert.isNotNull(value);
+// return String.valueOf(value.intValue());
+// }
+//
+// /**
+// * Converts the given long object to a string.
+// * Equivalent to String.valueOf(value.longValue())
.
+// *
+// * @param value the long object
+// * @return the string representing the given long value
+// */
+// public static String asString(Long value) {
+// Assert.isNotNull(value);
+// return String.valueOf(value.longValue());
+// }
+
+ /**
+ * Converts a font data array to a string. The string representation is
+ * that of asString(FontData) seperated by ';'
+ *
+ * @param value The font data.
+ * @return The string representation of the font data arra.
+ * @since 3.0
+ */
+ public static String asString(FontData[] value) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < value.length; i++) {
+ buffer.append(asString(value[i]));
+ if (i !is value.length - 1) {
+ buffer.append(FONT_SEPARATOR);
+ }
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Converts a font data object to a string. The string representation is
+ * "font name-style-height" (for example "Times New Roman-bold-36").
+ * @param value The font data.
+ * @return The string representation of the font data object.
+ */
+ public static String asString(FontData value) {
+ Assert.isNotNull(value);
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(value.getName());
+ buffer.append(SEPARATOR);
+ int style = value.getStyle();
+ bool bold = (style & DWT.BOLD) is DWT.BOLD;
+ bool italic = (style & DWT.ITALIC) is DWT.ITALIC;
+ if (bold && italic) {
+ buffer.append(BOLD_ITALIC);
+ } else if (bold) {
+ buffer.append(BOLD);
+ } else if (italic) {
+ buffer.append(ITALIC);
+ } else {
+ buffer.append(REGULAR);
+ }
+
+ buffer.append(SEPARATOR);
+ buffer.append(value.getHeight());
+ return buffer.toString();
+ }
+
+ /**
+ * Converts the given DWT point object to a string.
+ *
+ * The string representation of a point has the form
+ *
where
+ *
and
+ * are string representations of integers.
+ *
+ * The string representation of a rectangle has the form
+ *
+ * where
,
,
+ *
, and
+ * are string representations of integers.
+ *
+ * The string representation of an RGB color value has the form
+ *
,
,
are string representations of integers.
+ *
String.valueOf(value)
.
+ *
+ * @param value the bool value
+ * @return the string representing the given bool
+ */
+ public static String asString(bool value) {
+ return value ? "true" : "false";
+ }
+
+ /**
+ * Returns the given string with all whitespace characters removed.
+ *
+ * All characters that have codes less than or equal to '\u0020'
+ * (the space character) are considered to be a white space.
+ *
true
if the activation is done manually using
+ * {@link #show(Point)}
+ * @see #RECREATE
+ * @see #NO_RECREATE
+ */
+ public this(Control control, int style, bool manualActivation) {
+ super(control, style, manualActivation);
+ }
+
+ /**
+ * Creates the content are of the the tooltip. By default this creates a
+ * CLabel to display text. To customize the text Subclasses may override the
+ * following methods
+ * null
if no image should be
+ * displayed
+ */
+ protected Image getImage(Event event) {
+ return image;
+ }
+
+ /**
+ * The foreground {@link Color} used by {@link CLabel} in the default
+ * implementation
+ *
+ * @param event
+ * the event triggered the popup of the tooltip
+ * @return the {@link Color} or null
if default foreground
+ * color should be used
+ */
+ protected Color getForegroundColor(Event event) {
+ return (foregroundColor is null) ? event.widget.getDisplay()
+ .getSystemColor(DWT.COLOR_INFO_FOREGROUND) : foregroundColor;
+ }
+
+ /**
+ * The background {@link Color} used by {@link CLabel} in the default
+ * implementation
+ *
+ * @param event
+ * the event triggered the popup of the tooltip
+ * @return the {@link Color} or null
if default background
+ * color should be used
+ */
+ protected Color getBackgroundColor(Event event) {
+ return (backgroundColor is null) ? event.widget.getDisplay()
+ .getSystemColor(DWT.COLOR_INFO_BACKGROUND) : backgroundColor;
+ }
+
+ /**
+ * The background {@link Image} used by {@link CLabel} in the default
+ * implementation
+ *
+ * @param event
+ * the event triggered the popup of the tooltip
+ * @return the {@link Image} or null
if no image should be
+ * displayed in the background
+ */
+ protected Image getBackgroundImage(Event event) {
+ return backgroundImage;
+ }
+
+ /**
+ * The {@link Font} used by {@link CLabel} in the default implementation
+ *
+ * @param event
+ * the event triggered the popup of the tooltip
+ * @return the {@link Font} or null
if the default font
+ * should be used
+ */
+ protected Font getFont(Event event) {
+ return font;
+ }
+
+ /**
+ * The text displayed in the {@link CLabel} in the default implementation
+ *
+ * @param event
+ * the event triggered the popup of the tooltip
+ * @return the text or null
if no text has to be displayed
+ */
+ protected String getText(Event event) {
+ return text;
+ }
+
+ /**
+ * The background {@link Image} used by {@link CLabel} in the default
+ * implementation
+ *
+ * @param backgroundColor
+ * the {@link Color} or null
if default background
+ * color ({@link DWT#COLOR_INFO_BACKGROUND}) should be used
+ */
+ public void setBackgroundColor(Color backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ }
+
+ /**
+ * The background {@link Image} used by {@link CLabel} in the default
+ * implementation
+ *
+ * @param backgroundImage
+ * the {@link Image} or null
if no image should be
+ * displayed in the background
+ */
+ public void setBackgroundImage(Image backgroundImage) {
+ this.backgroundImage = backgroundImage;
+ }
+
+ /**
+ * The {@link Font} used by {@link CLabel} in the default implementation
+ *
+ * @param font
+ * the {@link Font} or null
if the default font
+ * should be used
+ */
+ public void setFont(Font font) {
+ this.font = font;
+ }
+
+ /**
+ * The foreground {@link Color} used by {@link CLabel} in the default
+ * implementation
+ *
+ * @param foregroundColor
+ * the {@link Color} or null
if default foreground
+ * color should be used
+ */
+ public void setForegroundColor(Color foregroundColor) {
+ this.foregroundColor = foregroundColor;
+ }
+
+ /**
+ * The {@link Image} displayed in the {@link CLabel} in the default
+ * implementation implementation
+ *
+ * @param image
+ * the {@link Image} or null
if no image should be
+ * displayed
+ */
+ public void setImage(Image image) {
+ this.image = image;
+ }
+
+ /**
+ * The style used to create the {@link CLabel} in the default implementation
+ *
+ * @param style
+ * the event triggered the popup of the tooltip
+ */
+ public void setStyle(int style) {
+ this.style = style;
+ }
+
+ /**
+ * The text displayed in the {@link CLabel} in the default implementation
+ *
+ * @param text
+ * the text or null
if no text has to be displayed
+ */
+ public void setText(String text) {
+ this.text = text;
+ }
+
+}
diff -r 1a6747be662d -r 8a302fdb4140 dwtx/jface/window/IShellProvider.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/window/IShellProvider.d Fri Mar 28 23:32:40 2008 +0100
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit true
if the activation is done manually using
+ * {@link #show(Point)}
+ * @see #RECREATE
+ * @see #NO_RECREATE
+ */
+ public this(Control control, int style, bool manualActivation) {
+ this.control = control;
+ this.style = style;
+ this.hideListener = new TooltipHideListener();
+ this.control.addDisposeListener(new class DisposeListener {
+
+ public void widgetDisposed(DisposeEvent e) {
+ deactivate();
+ }
+
+ });
+
+ this.listener = new ToolTipOwnerControlListener();
+
+ if (!manualActivation) {
+ activate();
+ }
+ }
+
+ /**
+ * Restore arbitary data under the given key
+ *
+ * @param key
+ * the key
+ * @param value
+ * the value
+ */
+ public void setData(String key, Object value) {
+ if (data is null) {
+ data = new HashMap!(String,Object);
+ }
+ data.add(key, value);
+ }
+
+ /**
+ * Get the data restored under the key
+ *
+ * @param key
+ * the key
+ * @return data or null
if no entry is restored under the key
+ */
+ public Object getData(String key) {
+ if (data !is null) {
+ return data.get(key);
+ }
+ return null;
+ }
+
+ /**
+ * Set the shift (from the mouse position triggered the event) used to
+ * display the tooltip. By default the tooltip is shifted 3 pixels to the
+ * left
+ *
+ * @param p
+ * the new shift
+ */
+ public void setShift(Point p) {
+ xShift = p.x;
+ yShift = p.y;
+ }
+
+ /**
+ * Activate tooltip support for this control
+ */
+ public void activate() {
+ deactivate();
+ control.addListener(DWT.Dispose, listener);
+ control.addListener(DWT.MouseHover, listener);
+ control.addListener(DWT.MouseMove, listener);
+ control.addListener(DWT.MouseExit, listener);
+ control.addListener(DWT.MouseDown, listener);
+ }
+
+ /**
+ * Deactivate tooltip support for the underlying control
+ */
+ public void deactivate() {
+ control.removeListener(DWT.Dispose, listener);
+ control.removeListener(DWT.MouseHover, listener);
+ control.removeListener(DWT.MouseMove, listener);
+ control.removeListener(DWT.MouseExit, listener);
+ control.removeListener(DWT.MouseDown, listener);
+ }
+
+ /**
+ * Return whther the tooltip respects bounds of the display.
+ *
+ * @return true
if the tooltip respects bounds of the display
+ */
+ public bool isRespectDisplayBounds() {
+ return respectDisplayBounds;
+ }
+
+ /**
+ * Set to false
if display bounds should not be respected or
+ * to true
if the tooltip is should repositioned to not
+ * overlap the display bounds.
+ *
+ * Default is true
+ *
true
if tooltip respects the bounds of the monitor
+ */
+ public bool isRespectMonitorBounds() {
+ return respectMonitorBounds;
+ }
+
+ /**
+ * Set to false
if monitor bounds should not be respected or
+ * to true
if the tooltip is should repositioned to not
+ * overlap the monitors bounds. The monitor the tooltip belongs to is the
+ * same is control's monitor the tooltip is shown for.
+ *
+ * Default is true
+ *
+ * Subclasses may overwrite this to get custom behaviour + *
+ * + * @param event + * the event + * @returntrue
if tooltip should be displayed
+ */
+ protected bool shouldCreateToolTip(Event event) {
+ if ((style & NO_RECREATE) !is 0) {
+ Object tmp = getToolTipArea(event);
+
+ // No new area close the current tooltip
+ if (tmp is null) {
+ hide();
+ return false;
+ }
+
+ bool rv = !tmp.opEquals(currentArea);
+ return rv;
+ }
+
+ return true;
+ }
+
+ /**
+ * This method is called before the tooltip is hidden
+ *
+ * @param event
+ * the event trying to hide the tooltip
+ * @return true
if the tooltip should be hidden
+ */
+ private bool shouldHideToolTip(Event event) {
+ if (event !is null && event.type is DWT.MouseMove
+ && (style & NO_RECREATE) !is 0) {
+ Object tmp = getToolTipArea(event);
+
+ // No new area close the current tooltip
+ if (tmp is null) {
+ hide();
+ return false;
+ }
+
+ bool rv = !tmp.opEquals(currentArea);
+ return rv;
+ }
+
+ return true;
+ }
+
+ /**
+ * This method is called to check for which area the tooltip is
+ * created/hidden for. In case of {@link #NO_RECREATE} this is used to
+ * decide if the tooltip is hidden recreated.
+ *
+ * By the default it is the widget the tooltip is created for but could be any object. To decide if
+ * the area changed the {@link Object#equals(Object)} method is used.
+ *
+ * @param event
+ * the event
+ * @return the area responsible for the tooltip creation or
+ * null
this could be any object describing the area
+ * (e.g. the {@link Control} onto which the tooltip is bound to, a part of
+ * this area e.g. for {@link ColumnViewer} this could be a
+ * {@link ViewerCell})
+ */
+ protected Object getToolTipArea(Event event) {
+ return control;
+ }
+
+ /**
+ * Start up the tooltip programmatically
+ *
+ * @param location
+ * the location relative to the control the tooltip is shown
+ */
+ public void show(Point location) {
+ Event event = new Event();
+ event.x = location.x;
+ event.y = location.y;
+ event.widget = control;
+ toolTipCreate(event);
+ }
+
+ private Shell toolTipCreate(Event event) {
+ if (shouldCreateToolTip(event)) {
+ Shell shell = new Shell(control.getShell(), DWT.ON_TOP | DWT.TOOL
+ | DWT.NO_FOCUS);
+ shell.setLayout(new FillLayout());
+
+ toolTipOpen(shell, event);
+
+ return shell;
+ }
+
+ return null;
+ }
+
+ private void toolTipShow(Shell tip, Event event) {
+ if (!tip.isDisposed()) {
+ currentArea = getToolTipArea(event);
+ createToolTipContentArea(event, tip);
+ if (isHideOnMouseDown()) {
+ toolTipHookBothRecursively(tip);
+ } else {
+ toolTipHookByTypeRecursively(tip, true, DWT.MouseExit);
+ }
+
+ tip.pack();
+ tip.setLocation(fixupDisplayBounds(tip.getSize(), getLocation(tip
+ .getSize(), event)));
+ tip.setVisible(true);
+ }
+ }
+
+ private Point fixupDisplayBounds(Point tipSize, Point location) {
+ if (respectDisplayBounds || respectMonitorBounds) {
+ Rectangle bounds;
+ Point rightBounds = new Point(tipSize.x + location.x, tipSize.y
+ + location.y);
+
+ dwt.widgets.Monitor.Monitor[] ms = control.getDisplay().getMonitors();
+
+ if (respectMonitorBounds && ms.length > 1) {
+ // By default present in the monitor of the control
+ bounds = control.getMonitor().getBounds();
+ Point p = new Point(location.x, location.y);
+
+ // Search on which monitor the event occurred
+ Rectangle tmp;
+ for (int i = 0; i < ms.length; i++) {
+ tmp = ms[i].getBounds();
+ if (tmp.contains(p)) {
+ bounds = tmp;
+ break;
+ }
+ }
+
+ } else {
+ bounds = control.getDisplay().getBounds();
+ }
+
+ if (!(bounds.contains(location) && bounds.contains(rightBounds))) {
+ if (rightBounds.x > bounds.width) {
+ location.x -= rightBounds.x - bounds.width;
+ }
+
+ if (rightBounds.y > bounds.height) {
+ location.y -= rightBounds.y - bounds.height;
+ }
+
+ if (location.x < bounds.x) {
+ location.x = bounds.x;
+ }
+
+ if (location.y < bounds.y) {
+ location.y = bounds.y;
+ }
+ }
+ }
+
+ return location;
+ }
+
+ /**
+ * Get the display relative location where the tooltip is displayed.
+ * Subclasses may overwrite to implement custom positioning.
+ *
+ * @param tipSize
+ * the size of the tooltip to be shown
+ * @param event
+ * the event triggered showing the tooltip
+ * @return the absolute position on the display
+ */
+ public Point getLocation(Point tipSize, Event event) {
+ return control.toDisplay(event.x + xShift, event.y + yShift);
+ }
+
+ private void toolTipHide(Shell tip, Event event) {
+ if (tip !is null && !tip.isDisposed() && shouldHideToolTip(event)) {
+ currentArea = null;
+ tip.dispose();
+ CURRENT_TOOLTIP = null;
+ afterHideToolTip(event);
+ }
+ }
+
+ private void toolTipOpen(Shell shell, Event event) {
+ // Ensure that only one Tooltip is shown in time
+ if (CURRENT_TOOLTIP !is null) {
+ toolTipHide(CURRENT_TOOLTIP, null);
+ }
+
+ CURRENT_TOOLTIP = shell;
+
+ if (popupDelay > 0) {
+ control.getDisplay().timerExec(popupDelay, new class Runnable {
+ Shell shell_;
+ Event event_;
+ this(){ shell_=shell; event_=event; }
+ public void run() {
+ toolTipShow(shell_, event_);
+ }
+ });
+ } else {
+ toolTipShow(CURRENT_TOOLTIP, event);
+ }
+
+ if (hideDelay > 0) {
+ control.getDisplay().timerExec(popupDelay + hideDelay,
+ new class Runnable {
+ Shell shell_;
+ this(){ shell_=shell; }
+ public void run() {
+ toolTipHide(shell, null);
+ }
+ });
+ }
+ }
+
+ private void toolTipHookByTypeRecursively(Control c, bool add, int type) {
+ if (add) {
+ c.addListener(type, hideListener);
+ } else {
+ c.removeListener(type, hideListener);
+ }
+
+ if ( auto c2 = cast(Composite)c ) {
+ Control[] children = c2.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ toolTipHookByTypeRecursively(children[i], add, type);
+ }
+ }
+ }
+
+ private void toolTipHookBothRecursively(Control c) {
+ c.addListener(DWT.MouseDown, hideListener);
+ c.addListener(DWT.MouseExit, hideListener);
+
+ if ( auto comp = cast(Composite) c ) {
+ Control[] children = comp.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ toolTipHookBothRecursively(children[i]);
+ }
+ }
+ }
+
+ /**
+ * Creates the content area of the the tooltip.
+ *
+ * @param event
+ * the event that triggered the activation of the tooltip
+ * @param parent
+ * the parent of the content area
+ * @return the content area created
+ */
+ protected abstract Composite createToolTipContentArea(Event event,
+ Composite parent);
+
+ /**
+ * This method is called after a Tooltip is hidden.
+ * + * Subclasses may override to clean up requested system resources + *
+ * + * @param event + * event triggered the hiding action (may benull
+ * if event wasn't triggered by user actions directly)
+ */
+ protected void afterHideToolTip(Event event) {
+
+ }
+
+ /**
+ * Set the hide delay.
+ *
+ * @param hideDelay
+ * the delay before the tooltip is hidden. If 0
+ * the tooltip is shown until user moves to other item
+ */
+ public void setHideDelay(int hideDelay) {
+ this.hideDelay = hideDelay;
+ }
+
+ /**
+ * Set the popup delay.
+ *
+ * @param popupDelay
+ * the delay before the tooltip is shown to the user. If
+ * 0
the tooltip is shown immediately
+ */
+ public void setPopupDelay(int popupDelay) {
+ this.popupDelay = popupDelay;
+ }
+
+ /**
+ * Return if hiding on mouse down is set.
+ *
+ * @return true
if hiding on mouse down in the tool tip is on
+ */
+ public bool isHideOnMouseDown() {
+ return hideOnMouseDown;
+ }
+
+ /**
+ * If you don't want the tool tip to be hidden when the user clicks inside
+ * the tool tip set this to false
. You maybe also need to
+ * hide the tool tip yourself depending on what you do after clicking in the
+ * tooltip (e.g. if you open a new {@link Shell})
+ *
+ * @param hideOnMouseDown
+ * flag to indicate of tooltip is hidden automatically on mouse
+ * down inside the tool tip
+ */
+ public void setHideOnMouseDown(bool hideOnMouseDown) {
+ // Only needed if there's currently a tooltip active
+ if (CURRENT_TOOLTIP !is null && !CURRENT_TOOLTIP.isDisposed()) {
+ // Only change if value really changed
+ if (hideOnMouseDown !is this.hideOnMouseDown) {
+ control.getDisplay().syncExec(new class Runnable {
+ bool hideOnMouseDown_;
+ this(){ hideOnMouseDown_=hideOnMouseDown; }
+ public void run() {
+ if (CURRENT_TOOLTIP !is null
+ && CURRENT_TOOLTIP.isDisposed()) {
+ toolTipHookByTypeRecursively(CURRENT_TOOLTIP,
+ hideOnMouseDown_, DWT.MouseDown);
+ }
+ }
+
+ });
+ }
+ }
+
+ this.hideOnMouseDown = hideOnMouseDown;
+ }
+
+ /**
+ * Hide the currently active tool tip
+ */
+ public void hide() {
+ toolTipHide(CURRENT_TOOLTIP, null);
+ }
+
+ private class ToolTipOwnerControlListener : Listener {
+ public void handleEvent(Event event) {
+ switch (event.type) {
+ case DWT.Dispose:
+ case DWT.KeyDown:
+ case DWT.MouseDown:
+ case DWT.MouseMove:
+ toolTipHide(CURRENT_TOOLTIP, event);
+ break;
+ case DWT.MouseHover:
+ toolTipCreate(event);
+ break;
+ case DWT.MouseExit:
+ /*
+ * Check if the mouse exit happend because we move over the
+ * tooltip
+ */
+ if (CURRENT_TOOLTIP !is null && !CURRENT_TOOLTIP.isDisposed()) {
+ if (CURRENT_TOOLTIP.getBounds().contains(
+ control.toDisplay(event.x, event.y))) {
+ break;
+ }
+ }
+
+ toolTipHide(CURRENT_TOOLTIP, event);
+ break;
+ }
+ }
+ }
+
+ private class TooltipHideListener : Listener {
+ public void handleEvent(Event event) {
+ if ( auto c = cast(Control)event.widget ) {
+
+ Shell shell = c.getShell();
+
+ switch (event.type) {
+ case DWT.MouseDown:
+ if (isHideOnMouseDown()) {
+ toolTipHide(shell, event);
+ }
+ break;
+ case DWT.MouseExit:
+ /*
+ * Give some insets to ensure we get exit informations from
+ * a wider area ;-)
+ */
+ Rectangle rect = shell.getBounds();
+ rect.x += 5;
+ rect.y += 5;
+ rect.width -= 10;
+ rect.height -= 10;
+
+ if (!rect.contains(c.getDisplay().getCursorLocation())) {
+ toolTipHide(shell, event);
+ }
+
+ break;
+ }
+ }
+ }
+ }
+}
diff -r 1a6747be662d -r 8a302fdb4140 dwtx/jface/window/Window.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/window/Window.d Fri Mar 28 23:32:40 2008 +0100
@@ -0,0 +1,1092 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit + * Creating a window involves the following steps: + *
Window
+ * create
(optional)WindowManager.add
(optional)open
+ * The JFace window framework (this package) consists of this class,
+ * Window
, the abstract base of all windows, and one concrete
+ * window classes (ApplicationWindow
) which may also be
+ * subclassed. Clients may define additional window subclasses as required.
+ *
+ * The Window
class provides methods that subclasses may
+ * override to configure the window, including:
+ *
close
- extend to free other DWT resourcesconfigureShell
- extend or reimplement to set shell
+ * properties before window openscreateContents
- extend or reimplement to create controls
+ * before window opensgetInitialSize
- reimplement to give the initial size for
+ * the shellgetInitialLocation
- reimplement to give the initial
+ * location for the shellgetShellListener
- extend or reimplement to receive shell
+ * eventshandleFontChange
- reimplement to respond to font changes
+ * handleShellCloseEvent
- extend or reimplement to handle
+ * shell closingsnull
if none.
+ *
+ * @see #setWindowManager
+ */
+ private WindowManager windowManager;
+
+ /**
+ * Window shell, or null
if none.
+ */
+ private Shell shell;
+
+ /**
+ * Top level DWT control, or null
if none
+ */
+ private Control contents;
+
+ /**
+ * Window return code; initially OK
.
+ *
+ * @see #setReturnCode
+ */
+ private int returnCode = OK;
+
+ /**
+ * true
if the open
method should not return
+ * until the window closes, and false
if the
+ * open
method should return immediately; initially
+ * false
(non-blocking).
+ *
+ * @see #setBlockOnOpen
+ */
+ private bool block = false;
+
+ /**
+ * Internal class for informing this window when fonts change.
+ */
+ private class FontChangeListener : IPropertyChangeListener {
+ public void propertyChange(PropertyChangeEvent event) {
+ handleFontChange(event);
+ }
+ }
+
+ /**
+ * Internal font change listener.
+ */
+ private FontChangeListener fontChangeListener;
+
+ /**
+ * Internal fields to detect if shell size has been set
+ */
+ private bool resizeHasOccurred = false;
+
+ private Listener resizeListener;
+
+ /**
+ * Creates a window instance, whose shell will be created under the given
+ * parent shell. Note that the window will have no visual representation
+ * until it is told to open. By default, open
does not block.
+ *
+ * @param parentShell
+ * the parent shell, or null
to create a top-level
+ * shell. Try passing "(Shell)null" to this method instead of "null"
+ * if your compiler complains about an ambiguity error.
+ * @see #setBlockOnOpen
+ * @see #getDefaultOrientation()
+ */
+ protected this(Shell parentShell) {
+ this(new SameShellProvider(parentShell));
+
+ if(parentShell is null) {
+ setShellStyle(getShellStyle() | getDefaultOrientation());
+ }
+ }
+
+ /**
+ * Creates a new window which will create its shell as a child of whatever
+ * the given shellProvider returns.
+ *
+ * @param shellProvider object that will return the current parent shell. Not null.
+ *
+ * @since 3.1
+ */
+ protected this(IShellProvider shellProvider) {
+ Assert.isNotNull(cast(Object)shellProvider);
+ this.parentShell = shellProvider;
+ }
+
+ /**
+ * Determines if the window should handle the close event or do nothing.
+ *
+ * The default implementation of this framework method returns
+ * true
, which will allow the
+ * handleShellCloseEvent
method to be called. Subclasses may
+ * extend or reimplement.
+ *
+ * This framework method may be extended (super.close
must
+ * be called).
+ *
true
if the window is (or was already) closed, and
+ * false
if it is still open
+ */
+ public bool close() {
+
+ // stop listening for font changes
+ if (fontChangeListener !is null) {
+ JFaceResources.getFontRegistry().removeListener(fontChangeListener);
+ fontChangeListener = null;
+ }
+
+ // remove this window from a window manager if it has one
+ if (windowManager !is null) {
+ windowManager.remove(this);
+ windowManager = null;
+ }
+
+ if (shell is null || shell.isDisposed()) {
+ return true;
+ }
+
+ // If we "close" the shell recursion will occur.
+ // Instead, we need to "dispose" the shell to remove it from the
+ // display.
+ shell.dispose();
+ shell = null;
+ contents = null;
+
+ return true;
+ }
+
+ /**
+ * Configures the given shell in preparation for opening this window in it.
+ * + * The default implementation of this framework method sets the shell's + * image and gives it a grid layout. Subclasses may extend or reimplement. + *
+ * + * @param newShell + * the shell + */ + protected void configureShell(Shell newShell) { + + // The single image version of this code had a comment related to bug + // 46624, + // and some code that did nothing if the stored image was already + // disposed. + // The equivalent in the multi-image version seems to be to remove the + // disposed images from the array passed to the shell. + if (defaultImages !is null && defaultImages.length > 0) { + auto nonDisposedImages = new ArraySeq!(Image); + nonDisposedImages.capacity(defaultImages.length); + for (int i = 0; i < defaultImages.length; ++i) { + if (defaultImages[i] !is null && !defaultImages[i].isDisposed()) { + nonDisposedImages.append(defaultImages[i]); + } + } + + if (nonDisposedImages.size() <= 0) { + Stderr.formatln("Window.configureShell: images disposed"); //$NON-NLS-1$ + } else { + newShell.setImages(nonDisposedImages.toArray()); + } + } + + Layout layout = getLayout(); + if (layout !is null) { + newShell.setLayout(layout); + } + } + + /** + * Creates the layout for the shell. The layout created here will be + * attached to the composite passed into createContents. The default + * implementation returns a GridLayout with no margins. Subclasses that + * change the layout type by overriding this method should also override + * createContents. + * + *+ * A return value of null indicates that no layout should be attached to the + * composite. In this case, the layout may be attached within + * createContents. + *
+ * + * @return a newly created Layout or null if no layout should be attached. + * @since 3.0 + */ + protected Layout getLayout() { + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + return layout; + } + + /** + * Constrain the shell size to be no larger than the display bounds. + * + * @since 2.0 + */ + protected void constrainShellSize() { + // limit the shell size to the display size + Rectangle bounds = shell.getBounds(); + Rectangle constrained = getConstrainedShellBounds(bounds); + if (!bounds.opEquals(constrained)) { + shell.setBounds(constrained); + } + } + + /** + * Creates this window's widgetry in a new top-level shell. + *
+ * The default implementation of this framework method creates this window's
+ * shell (by calling createShell
), and its controls (by
+ * calling createContents
), then initializes this window's
+ * shell bounds (by calling initializeBounds
).
+ *
+ * It is common practise to create and return a single composite that + * contains the entire window contents. + *
+ * + *
+ * The default implementation of this framework method creates an instance
+ * of Composite
. Subclasses may override.
+ *
+ * The default implementation of this framework method creates a new shell
+ * and configures it using configureShell. Rather than
+ * override this method, subclasses should instead override
+ *
configureShell.
+ *
null
if this window's
+ * control has not been created yet
+ */
+ protected Control getContents() {
+ return contents;
+ }
+
+ /**
+ * Returns the default image. This is the image that will be used for
+ * windows that have no shell image at the time they are opened. There is no
+ * default image unless one is installed via setDefaultImage
.
+ *
+ * @return the default image, or null
if none
+ * @see #setDefaultImage
+ */
+ public static Image getDefaultImage() {
+ return (defaultImages is null || defaultImages.length < 1) ? null
+ : defaultImages[0];
+ }
+
+ /**
+ * Returns the array of default images to use for newly opened windows. It
+ * is expected that the array will contain the same icon rendered at
+ * different resolutions.
+ *
+ * @see dwt.widgets.Decorations#setImages(dwt.graphics.Image[])
+ *
+ * @return the array of images to be used when a new window is opened
+ * @see #setDefaultImages
+ * @since 3.0
+ */
+ public static Image[] getDefaultImages() {
+ return (defaultImages is null ? new Image[0] : defaultImages);
+ }
+
+ /**
+ * Returns the initial location to use for the shell. The default
+ * implementation centers the shell horizontally (1/2 of the difference to
+ * the left and 1/2 to the right) and vertically (1/3 above and 2/3 below)
+ * relative to the parent shell, or display bounds if there is no parent
+ * shell.
+ *
+ * @param initialSize
+ * the initial size of the shell, as returned by
+ * getInitialSize
.
+ * @return the initial location of the shell
+ */
+ protected Point getInitialLocation(Point initialSize) {
+ Composite parent = shell.getParent();
+
+ dwt.widgets.Monitor.Monitor monitor = shell.getDisplay().getPrimaryMonitor();
+ if (parent !is null) {
+ monitor = parent.getMonitor();
+ }
+
+ Rectangle monitorBounds = monitor.getClientArea();
+ Point centerPoint;
+ if (parent !is null) {
+ centerPoint = Geometry.centerPoint(parent.getBounds());
+ } else {
+ centerPoint = Geometry.centerPoint(monitorBounds);
+ }
+
+ return new Point(centerPoint.x - (initialSize.x / 2), Math.max(
+ monitorBounds.y, Math.min(centerPoint.y
+ - (initialSize.y * 2 / 3), monitorBounds.y
+ + monitorBounds.height - initialSize.y)));
+ }
+
+ /**
+ * Returns the initial size to use for the shell. The default implementation
+ * returns the preferred size of the shell, using
+ * Shell.computeSize(DWT.DEFAULT, DWT.DEFAULT, true)
.
+ *
+ * @return the initial size of the shell
+ */
+ protected Point getInitialSize() {
+ return shell.computeSize(DWT.DEFAULT, DWT.DEFAULT, true);
+ }
+
+ /**
+ * Returns the most specific modal child from the given list of Shells.
+ *
+ * @param toSearch shells to search for modal children
+ * @return the most specific modal child, or null if none
+ *
+ * @since 3.1
+ */
+ private static Shell getModalChild(Shell[] toSearch) {
+ int modal = DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL | DWT.PRIMARY_MODAL;
+
+ for (int i = toSearch.length - 1; i >= 0; i--) {
+ Shell shell = toSearch[i];
+
+ // Check if this shell has a modal child
+ Shell[] children = shell.getShells();
+ Shell modalChild = getModalChild(children);
+ if (modalChild !is null) {
+ return modalChild;
+ }
+
+ // If not, check if this shell is modal itself
+ if (shell.isVisible() && (shell.getStyle() & modal) !is 0) {
+ return shell;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns parent shell, under which this window's shell is created.
+ *
+ * @return the parent shell, or null
if there is no parent
+ * shell
+ */
+ protected Shell getParentShell() {
+ Shell parent = parentShell.getShell();
+
+ int modal = DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL | DWT.PRIMARY_MODAL;
+
+ if ((getShellStyle() & modal) !is 0) {
+ // If this is a modal shell with no parent, pick a shell using defaultModalParent.
+ if (parent is null) {
+ parent = defaultModalParent.getShell();
+ }
+ }
+
+ return parent;
+ }
+
+ /**
+ * Returns this window's return code. A window's return codes are
+ * window-specific, although two standard return codes are predefined:
+ * OK
and CANCEL
.
+ *
+ * @return the return code
+ */
+ public int getReturnCode() {
+ return returnCode;
+ }
+
+ /**
+ * Returns this window's shell.
+ *
+ * @return this window's shell, or null
if this window's
+ * shell has not been created yet
+ */
+ public Shell getShell() {
+ return shell;
+ }
+
+ /**
+ * Returns a shell listener. This shell listener gets registered with this
+ * window's shell.
+ *
+ * The default implementation of this framework method returns a new
+ * listener that makes this window the active window for its window manager
+ * (if it has one) when the shell is activated, and calls the framework
+ * method handleShellCloseEvent
when the shell is closed.
+ * Subclasses may extend or reimplement.
+ *
+ * The default value is DWT.CLOSE|DWT.MIN|DWT.MAX|DWT.RESIZE
.
+ * Subclassers should call setShellStyle
to change this
+ * value, rather than overriding this method.
+ *
null
if none
+ */
+ public WindowManager getWindowManager() {
+ return windowManager;
+ }
+
+ /**
+ * Notifies of a font property change.
+ * + * The default implementation of this framework method does nothing. + * Subclasses may reimplement. + *
+ * + * @param event + * the property change event detailing what changed + */ + protected void handleFontChange(PropertyChangeEvent event) { + // do nothing + } + + /** + * Notifies that the window's close button was pressed, the close menu was + * selected, or the ESCAPE key pressed. + *
+ * The default implementation of this framework method sets the window's
+ * return code to CANCEL
and closes the window using
+ * close
. Subclasses may extend or reimplement.
+ *
+ * This framework method is called by the create
framework
+ * method. The default implementation calls getInitialSize
+ * and getInitialLocation
and passes the results to
+ * Shell.setBounds
. This is only done if the bounds of the
+ * shell have not already been modified. Subclasses may extend or
+ * reimplement.
+ *
+ * If this window has been configured to block on open (
+ * setBlockOnOpen
), this method waits until the window is
+ * closed by the end user, and then it returns the window's return code;
+ * otherwise, this method returns immediately. A window's return codes are
+ * window-specific, although two standard return codes are predefined:
+ * OK
and CANCEL
.
+ *
open
method should block until the window
+ * closes.
+ *
+ * @param shouldBlock
+ * true
if the open
method should
+ * not return until the window closes, and false
+ * if the open
method should return immediately
+ */
+ public void setBlockOnOpen(bool shouldBlock) {
+ block = shouldBlock;
+ }
+
+ /**
+ * Sets the default image. This is the image that will be used for windows
+ * that have no shell image at the time they are opened. There is no default
+ * image unless one is installed via this method.
+ *
+ * @param image
+ * the default image, or null
if none
+ */
+ public static void setDefaultImage(Image image) {
+ defaultImages = image is null ? null : [ image ];
+ }
+
+ /**
+ * Sets the array of default images to use for newly opened windows. It is
+ * expected that the array will contain the same icon rendered at different
+ * resolutions.
+ *
+ * @see dwt.widgets.Decorations#setImages(dwt.graphics.Image[])
+ *
+ * @param images
+ * the array of images to be used when this window is opened
+ * @since 3.0
+ */
+ public static void setDefaultImages(Image[] images) {
+ Image[] newArray = new Image[images.length];
+ System.arraycopy(images, 0, newArray, 0, newArray.length);
+ defaultImages = newArray;
+ }
+
+ /**
+ * Changes the parent shell. This is only safe to use when the shell is not
+ * yet realized (i.e., created). Once the shell is created, it must be
+ * disposed (i.e., closed) before this method can be called.
+ *
+ * @param newParentShell
+ * The new parent shell; this value may be null
if
+ * there is to be no parent.
+ * @since 3.1
+ */
+ protected void setParentShell(Shell newParentShell) {
+ Assert.isTrue((shell is null), "There must not be an existing shell."); //$NON-NLS-1$
+ parentShell = new SameShellProvider(newParentShell);
+ }
+
+ /**
+ * Sets this window's return code. The return code is automatically returned
+ * by open
if block on open is enabled. For non-blocking
+ * opens, the return code needs to be retrieved manually using
+ * getReturnCode
.
+ *
+ * @param code
+ * the return code
+ */
+ protected void setReturnCode(int code) {
+ returnCode = code;
+ }
+
+ /**
+ * Returns the monitor whose client area contains the given point. If no
+ * monitor contains the point, returns the monitor that is closest to the
+ * point. If this is ever made public, it should be moved into a separate
+ * utility class.
+ *
+ * @param toSearch
+ * point to find (display coordinates)
+ * @param toFind
+ * point to find (display coordinates)
+ * @return the montor closest to the given point
+ */
+ private static dwt.widgets.Monitor.Monitor getClosestMonitor(Display toSearch, Point toFind) {
+ int closest = Integer.MAX_VALUE;
+
+ dwt.widgets.Monitor.Monitor[] monitors = toSearch.getMonitors();
+ dwt.widgets.Monitor.Monitor result = monitors[0];
+
+ for (int idx = 0; idx < monitors.length; idx++) {
+ dwt.widgets.Monitor.Monitor current = monitors[idx];
+
+ Rectangle clientArea = current.getClientArea();
+
+ if (clientArea.contains(toFind)) {
+ return current;
+ }
+
+ int distance = Geometry.distanceSquared(Geometry
+ .centerPoint(clientArea), toFind);
+ if (distance < closest) {
+ closest = distance;
+ result = current;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Given the desired position of the window, this method returns an adjusted
+ * position such that the window is no larger than its monitor, and does not
+ * extend beyond the edge of the monitor. This is used for computing the
+ * initial window position, and subclasses can use this as a utility method
+ * if they want to limit the region in which the window may be moved.
+ *
+ * @param preferredSize
+ * the preferred position of the window
+ * @return a rectangle as close as possible to preferredSize that does not
+ * extend outside the monitor
+ *
+ * @since 3.0
+ */
+ protected Rectangle getConstrainedShellBounds(Rectangle preferredSize) {
+ Rectangle result = new Rectangle(preferredSize.x, preferredSize.y,
+ preferredSize.width, preferredSize.height);
+
+ dwt.widgets.Monitor.Monitor mon = getClosestMonitor(getShell().getDisplay(), Geometry
+ .centerPoint(result));
+
+ Rectangle bounds = mon.getClientArea();
+
+ if (result.height > bounds.height) {
+ result.height = bounds.height;
+ }
+
+ if (result.width > bounds.width) {
+ result.width = bounds.width;
+ }
+
+ result.x = Math.max(bounds.x, Math.min(result.x, bounds.x
+ + bounds.width - result.width));
+ result.y = Math.max(bounds.y, Math.min(result.y, bounds.y
+ + bounds.height - result.height));
+
+ return result;
+ }
+
+ /**
+ * Sets the shell style bits. This method has no effect after the shell is
+ * created.
+ *
+ * The shell style bits are used by the framework method
+ * createShell
when creating this window's shell.
+ *
+ * Note that this method is used by WindowManager
to maintain
+ * a backpointer. Clients must not call the method directly.
+ *
null
if none
+ */
+ public void setWindowManager(WindowManager manager) {
+ windowManager = manager;
+
+ // Code to detect invalid usage
+
+ if (manager !is null) {
+ Window[] windows = manager.getWindows();
+ for (int i = 0; i < windows.length; i++) {
+ if (windows[i] is this) {
+ return;
+ }
+ }
+ manager.add(this);
+ }
+ }
+
+ /**
+ * Sets the exception handler for this application.
+ * + * Note that the handler may only be set once. Subsequent calls to this method will be + * ignored. + *
+ *
+ * @param handler
+ * the exception handler for the application.
+ */
+ public static void setExceptionHandler(IExceptionHandler handler) {
+ if ( cast(DefaultExceptionHandler)exceptionHandler ) {
+ exceptionHandler = handler;
+ }
+ }
+
+ /**
+ * Sets the default parent for modal Windows. This will be used to locate
+ * the parent for any modal Window constructed with a null parent.
+ *
+ * @param provider shell provider that will be used to locate the parent shell
+ * whenever a Window is created with a null parent
+ * @since 3.1
+ */
+ public static void setDefaultModalParent(IShellProvider provider) {
+ defaultModalParent = provider;
+ }
+
+ /**
+ * Gets the default orientation for windows. If it is not
+ * set the default value will be unspecified (DWT#NONE).
+ *
+ *
+ * @return DWT#NONE, DWT.RIGHT_TO_LEFT or DWT.LEFT_TO_RIGHT
+ * @see DWT#RIGHT_TO_LEFT
+ * @see DWT#LEFT_TO_RIGHT
+ * @see DWT#NONE
+ * @since 3.1
+ */
+ public static int getDefaultOrientation() {
+ return orientation;
+
+ }
+
+ /**
+ * Sets the default orientation of windows.
+ * @param defaultOrientation one of
+ * DWT#RIGHT_TO_LEFT, DWT#LEFT_TO_RIGHT ,DWT#NONE
+ * @see DWT#RIGHT_TO_LEFT
+ * @see DWT#LEFT_TO_RIGHT
+ * @see DWT#NONE
+ * @since 3.1
+ */
+ public static void setDefaultOrientation(int defaultOrientation) {
+ orientation = defaultOrientation;
+
+ }
+
+}
diff -r 1a6747be662d -r 8a302fdb4140 dwtx/jface/window/WindowManager.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/window/WindowManager.d Fri Mar 28 23:32:40 2008 +0100
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ * Frank Benoit
+ * Creating a window manager is as simple as creating an instance of
+ * WindowManager
. Associating a window with a window manager is
+ * done with WindowManager.add(Window)
. A window is automatically
+ * removed from its window manager as a side effect of closing the window.
+ * Window
).
+ */
+ private ArraySeq!(Window) windows;
+
+ /**
+ * List of window managers who have this window manager
+ * as their parent (element type: WindowManager
).
+ */
+ private Seq!(WindowManager) subManagers;
+
+ /**
+ * Creates an empty window manager without a parent window
+ * manager (that is, a root window manager).
+ */
+ public this() {
+ windows = new ArraySeq!(Window);
+ }
+
+ /**
+ * Creates an empty window manager with the given
+ * window manager as parent.
+ *
+ * @param parent the parent window manager
+ */
+ public this(WindowManager parent) {
+ windows = new ArraySeq!(Window);
+ Assert.isNotNull(parent);
+ parent.addWindowManager(this);
+ }
+
+ /**
+ * Adds the given window to the set of windows managed by
+ * this window manager. Does nothing is this window is
+ * already managed by this window manager.
+ *
+ * @param window the window
+ */
+ public void add(Window window) {
+ if (!windows.contains(window)) {
+ windows.append(window);
+ window.setWindowManager(this);
+ }
+ }
+
+ /**
+ * Adds the given window manager to the list of
+ * window managers that have this one as a parent.
+ *
true
if all windows were sucessfully closed,
+ * and false
if any window refused to close
+ */
+ public bool close() {
+ auto t = windows.dup(); // make iteration robust
+ foreach( window; t ){
+ bool closed = window.close();
+ if (!closed) {
+ return false;
+ }
+ }
+ if (subManagers !is null) {
+ foreach( wm; subManagers ){
+ bool closed = wm.close();
+ if (!closed) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns this window manager's number of windows
+ *
+ * @return the number of windows
+ * @since 3.0
+ */
+ public int getWindowCount() {
+ return windows.size();
+ }
+
+ /**
+ * Returns this window manager's set of windows.
+ *
+ * @return a possibly empty list of window
+ */
+ public Window[] getWindows() {
+ return windows.toArray();
+ }
+
+ /**
+ * Removes the given window from the set of windows managed by
+ * this window manager. Does nothing is this window is
+ * not managed by this window manager.
+ *
+ * @param window the window
+ */
+ public final void remove(Window window) {
+ if (windows.contains(window)) {
+ windows.remove(window);
+ window.setWindowManager(null);
+ }
+ }
+}