Index: src/swingwt/awt/image/BufferedImageOp.java =================================================================== --- src/swingwt/awt/image/BufferedImageOp.java (revision 0) +++ src/swingwt/awt/image/BufferedImageOp.java (revision 0) @@ -0,0 +1,27 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwt.awt.image; + +import swingwt.awt.RenderingHints; +import swingwt.awt.geom.Point2D; +import swingwt.awt.geom.Rectangle2D; + + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public interface BufferedImageOp { + public BufferedImage filter(BufferedImage src, BufferedImage dest); + public Rectangle2D getBounds2D (BufferedImage src); + public BufferedImage createCompatibleDestImage (BufferedImage src, ColorModel destCM); + public Point2D getPoint2D (Point2D srcPt, Point2D dstPt); + public RenderingHints getRenderingHints(); + +} Index: src/swingwt/awt/Window.java =================================================================== --- src/swingwt/awt/Window.java (revision 85) +++ src/swingwt/awt/Window.java (working copy) @@ -12,16 +12,26 @@ package swingwt.awt; -import org.eclipse.swt.widgets.*; -import org.eclipse.swt.*; -import org.eclipse.swt.events.*; +import java.util.Iterator; +import java.util.Vector; -import swingwtx.swing.*; -import java.util.*; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ShellEvent; +import org.eclipse.swt.events.ShellListener; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import swingwtx.swing.JButton; +import swingwtx.swing.JMenuBar; +import swingwtx.swing.JRootPane; +import swingwtx.swing.SwingUtilities; +import swingwtx.swing.SwingUtilities.SwingWTRunnable; +import swingwtx.swing.SwingWTUtils; + public class Window extends Container { - protected Shell peer = null; + //protected Shell peer = null; protected Display display = null; protected Vector windowListeners = new Vector(); protected boolean isClosed = false; @@ -42,8 +52,6 @@ /** Number of pixels to allow for frame decoration during pack() */ protected final static int FRAME_DECORATION_WIDTH = 8; - private Object retval = null; - /** Does nothing */ GraphicsConfiguration graphicsConfig = null; @@ -92,6 +100,7 @@ SwingUtilities.invokeSync(new Runnable() { public void run() { createImpl(SWTFrameType); + queuedValidate(); } }); } @@ -108,49 +117,58 @@ display = SwingWTUtils.getDisplay(); if (parent == null) - peer = new Shell(display, SWTFrameType); + peer = new Shell(display, SWTFrameType); else - peer = new Shell( (Shell)parent.getSWTPeer(), SWTFrameType); + peer = new Shell( (Shell)parent.getSWTPeer(), SWTFrameType); - composite = peer; - peer.setLayout(new swingwt.awt.swtcustomlayout.SWTBorderLayout()); - peer.setLayoutData(swingwt.awt.swtcustomlayout.SWTBorderLayout.CENTER); - peer.addShellListener(createShellListener()); + // register the shell + SwingWTUtils.registerWrapper(this, peer); - setCachedProperties(); + Shell shell = (Shell) peer; + composite = shell; + shell.setLayout(new swingwt.awt.swtcustomlayout.SWTBorderLayout()); + shell.setLayoutData(swingwt.awt.swtcustomlayout.SWTBorderLayout.CENTER); + shell.addShellListener(createShellListener()); - try { rootPane.setSwingWTParent(this); } catch (Exception e) { e.printStackTrace(); } + assertCachedProperties(); + try { + + // This will trigger the whole GUI creation on the root pane. + rootPane.setSwingWTParent(this); + + } catch (Exception e) { + e.printStackTrace(); + } isClosed = false; } - public void setCachedProperties() { - if (!SwingWTUtils.isSWTControlAvailable(peer)) return; - if (title != null) peer.setText(title); - if (iconImage != null) peer.setImage(iconImage.image); - if (pMenu != null) setJMenuBar(pMenu); - if (pLocation != null) setLocationImpl(pLocation); - if (pSize != null) setSizeImpl(pSize); + + public void assertCachedProperties() { + // TODO - should we call super.assertCachedProperties() ? + if (hasPeer()) { + Shell shell = (Shell) peer; + if (title != null) shell.setText(title); + if (iconImage != null) shell.setImage(iconImage.image); + if (pMenu != null) setJMenuBar(pMenu); + if (pLocation != null) + setPeerLocation(pLocation); + else + setPeerLocation(new Point(0, 0)); + if (pSize != null) setSizeImpl(pSize); + } } - /** FIXME: Bad algorithm here, but can't find appropriate routine. Display.map() looks - * interesting, but it is undocumented. - */ + /* + * Thiago - I fixed Component.getLocationOnScreen, so I am not sure + * this code is necessary. + * TODO - remove this if it proves to be unneeded. public Point getLocationOnScreen() { return getLocation(); - /* - final Point p = new Point(0, 0); - if (!SwingWTUtils.isSWTControlAvailable(peer)) return p; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - p.x = peer.getLocation().x + getLocation().x; - p.y = peer.getLocation().y + getLocation().y; - } - }); - return p; - */ } + */ + /** Overridden to point to getContentPane() rather than throwing an error */ public Component add(swingwt.awt.Component c) { rootPane.getContentPane().add(c); return c; } /** Overridden to point to getContentPane() rather than throwing an error */ @@ -185,26 +203,28 @@ public void setForeground(swingwt.awt.Color c) { rootPane.setForeground(c); } public boolean isForegroundSet() { return rootPane.isForegroundSet(); } + public void pack() { - final Window me = this; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - Dimension d = rootPane.getContentPane().getPreferredSize(); - rootPane.setSize(d); - rootPane.getContentPane().setSize(d); - if (SwingWTUtils.isSWTControlAvailable(peer)) { - pSize = new Dimension(d.width + frameWidth, d.height + frameHeight); - peer.setSize(pSize.width, pSize.height); - } else { - // Set pSize to some valid, but slightly bogus value - since we don't know what the actual - // frameWidth and frameHeight will be once SWT makes the window. This will be adjusted when - // the window gets created via delayPack. - pSize = new Dimension(d.width + FRAME_DECORATION_WIDTH, d.height + FRAME_DECORATION_HEIGHT); - // Save the content pane preferred size for when the shell is created - delayPack = new Dimension(d); - } - } - }); + + final Dimension d = rootPane.getContentPane().getPreferredSize(); + rootPane.setSize(d); + rootPane.getContentPane().setSize(d); + + if (hasPeer()) { + SwingUtilities.invokeSync(new Runnable() { + public void run() { + pSize = new Dimension(d.width + frameWidth, d.height + frameHeight); + peer.setSize(pSize.width, pSize.height); + } + }); + } else { + // Set pSize to some valid, but slightly bogus value - since we don't know what the actual + // frameWidth and frameHeight will be once SWT makes the window. This will be adjusted when + // the window gets created via delayPack. + pSize = new Dimension(d.width + FRAME_DECORATION_WIDTH, d.height + FRAME_DECORATION_HEIGHT); + // Save the content pane preferred size for when the shell is created + delayPack = new Dimension(d); + } } public void setLocationRelativeTo(Component c) { @@ -221,19 +241,25 @@ public void setLocation(Point p) { if (SwingWTUtils.isMacOSX() && (p.y == 0)) p.y = SwingWTUtils.MACOSX_MENUBAR_BOTTOM; - if (!p.equals(pLocation)) { - setLocationImpl(p); - } + + if (! p.equals(pLocation)) + setPeerLocation(p); + + pLocation = p; } - private void setLocationImpl(Point p) { - pLocation = p; - if (SwingWTUtils.isSWTControlAvailable(peer)) { + + /** + * Sets the peer location, without changing the local cache. + * + * @param p + */ + private void setPeerLocation(final Point p) { + if (hasPeer()) SwingUtilities.invokeSync(new Runnable() { public void run() { - peer.setLocation(pLocation.x, pLocation.y); + peer.setLocation(p.x, p.y); } }); - } } public Point getLocation() { return getBounds().getLocation(); @@ -242,6 +268,7 @@ public void setSize(final int width, final int height) { setSize(new Dimension(width, height)); } + public void setSize(Dimension d) { if (!d.equals(pSize)) { // If setSize() is called after pack() and the size differs, reset the delayed pack() @@ -251,14 +278,15 @@ } private void setSizeImpl(Dimension d) { pSize = d; - if (SwingWTUtils.isSWTControlAvailable(peer)) { + + if (hasPeer()) SwingUtilities.invokeSync(new Runnable() { public void run() { peer.setSize(pSize.width, pSize.height); } }); - } } + public Dimension getSize() { return getBounds().getSize(); } @@ -271,35 +299,15 @@ setLocation(x, y); setSize(width, height); } - public Rectangle getBounds() { - if (SwingWTUtils.isSWTControlAvailable(peer)) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - retval = new Rectangle(peer.getLocation().x, peer.getLocation().y, peer.getSize().x, peer.getSize().y); - } - }); - return (Rectangle) retval; - } - else { - Rectangle rect = new Rectangle(0, 0, 0, 0); - if (pLocation != null) { - rect.setLocation(pLocation); - } - if (pSize != null) { - rect.setSize(pSize); - } - return rect; - } - } - + + public boolean isActive() { - final boolean[] ret = new boolean[1]; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - ret[0] = (SwingWTUtils.getDisplay().getActiveShell() == peer); - } - }); - return ret[0]; + + return hasPeer() && ((Boolean) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return Boolean.valueOf(SwingWTUtils.getDisplay().getActiveShell() == peer); + } + })).booleanValue(); } public boolean isFocused() { @@ -313,147 +321,140 @@ public void setCursor(final swingwt.awt.Cursor c) { // We have to override this because peer in Component is - // not this Shell component + // not this Shell component pCursor = c; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - try { - if (SwingWTUtils.isSWTControlAvailable(peer)) { - if (c != null) { - peer.setCursor(c.getSWTCursor()); - } else { - peer.setCursor(null); + + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + try { + if (c != null) { + peer.setCursor(c.getSWTCursor()); + } else { + peer.setCursor(null); + } + } catch (IllegalArgumentException e) { + } catch (Exception e) { + e.printStackTrace(); } } - } catch (IllegalArgumentException e) { - } catch (Exception e) { - e.printStackTrace(); - } - } - }); + }); } - public void setVisible(final boolean b) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (b) { - if (!SwingWTUtils.isSWTControlAvailable(peer)) - create(); - if (!hasBeenOpened) { - peer.open(); + public void setVisible(final boolean visible) { + + if (visible) { + // note that create() will be executed in a sync call so it does not have + // to be inside the subsequent invokeSync + if (! hasPeer()) + create(); + + SwingUtilities.invokeSync(new Runnable() { + public void run() { + if (!hasBeenOpened) { + ((Shell) peer).open(); processWindowEvent(swingwt.awt.event.WindowEvent.WINDOW_OPENED); repaintFix(); hasBeenOpened = true; } else { peer.setVisible(true); - } - } - else { - if (hasBeenOpened) - peer.setVisible(false); - } - } - }); + } } + }); + + } else { + if (hasBeenOpened) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + peer.setVisible(false); + } + }); + } } /** Closes the Window and releases all components */ public void dispose() { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - // If the Window is already closing because the user hit the x - // button, don't do anything - if (isClosed) return; - if (SwingWTUtils.isSWTControlAvailable(peer)) { - peer.dispose(); - } - } - }); + if (! isClosed && hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + peer.dispose(); + } + }); + super.dispose(); } public String getTitle() { - if (SwingWTUtils.isSWTControlAvailable(peer)) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - retval = peer.getText(); + if (hasPeer()) + return (String) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return ((Shell) peer).getText(); } }); - } - else retval = title; - return retval.toString(); + return title; } - public void setTitle(String s) { - this.title = s; - if (SwingWTUtils.isSWTControlAvailable(peer)) { + public void setTitle(final String title) { + this.title = title; + + if (hasPeer()) SwingUtilities.invokeSync(new Runnable() { public void run() { - peer.setText(title); + ((Shell) peer).setText(title); } }); - } } public Image getIconImage() { - final Image[] ret = new Image[1]; - if (SwingWTUtils.isSWTControlAvailable(peer)) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - ret[0] = new Image(); - ret[0].image = peer.getImage(); + if (hasPeer()) + return (Image) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return new Image(((Shell) peer).getImage()); } }); - } - else ret[0] = iconImage; - return ret[0]; + return iconImage; } public void setIconImage(final Image icon) { this.iconImage = icon; - if (SwingWTUtils.isSWTControlAvailable(peer)) { + + if (hasPeer()) SwingUtilities.invokeSync(new Runnable() { public void run() { - peer.setImage(icon.image); + ((Shell) peer).setImage(icon.image); } }); - } } public void setJMenuBar(JMenuBar menu) { this.pMenu = menu; - if (SwingWTUtils.isSWTControlAvailable(peer)) { + + if (hasPeer()) rootPane.setJMenuBar(menu); - } } public JMenuBar getJMenuBar() { - if (SwingWTUtils.isSWTControlAvailable(peer)) { - retval = rootPane.getJMenuBar(); - } - else { - retval = pMenu; - } - return (JMenuBar) retval; + if (hasPeer()) + return rootPane.getJMenuBar(); + + return pMenu; } public void setMenuBar(MenuBar menu) { this.pMenuBar = menu; - if (SwingWTUtils.isSWTControlAvailable(peer)) { + + if (hasPeer()) rootPane.setMenuBar(menu); - } } public MenuBar getMenuBar() { - if (SwingWTUtils.isSWTControlAvailable(peer)) { - retval = rootPane.getMenuBar(); - } - else { - retval = pMenuBar; - } - return (MenuBar) retval; + + if (hasPeer()) + return rootPane.getMenuBar(); + + return pMenuBar; } public void setDefaultButton(JButton button) { @@ -466,8 +467,8 @@ protected class WindowShellListener implements ShellListener { public void shellActivated(ShellEvent e) { - frameWidth = peer.getSize().x - peer.getClientArea().width; - frameHeight = peer.getSize().y - peer.getClientArea().height; + frameWidth = peer.getSize().x - ((Shell) peer).getClientArea().width; + frameHeight = peer.getSize().y - ((Shell) peer).getClientArea().height; if (delayPack != null) { pSize = new Dimension(delayPack.width + frameWidth, delayPack.height + frameHeight); peer.setSize(pSize.width, pSize.height); @@ -533,7 +534,7 @@ } protected void dispatchEvents() { - while (!peer.isDisposed()) { + while (null != peer && ! peer.isDisposed()) { try { if (!display.readAndDispatch()) { // Send this thread to sleep to allow other @@ -562,28 +563,27 @@ /** Sends the window to the front */ public void toFront() { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) - peer.forceActive(); - } - }); + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + ((Shell) peer).forceActive(); + } + }); } /** Sends the window to the back */ public void toBack() { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) { + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { // Find another shell to make active Shell[] s = SwingWTUtils.getDisplay().getShells(); for (int i = 0; i < s.length; i++) { if (!s[i].equals(peer)) s[i].forceActive(); } - } - } - }); + } + }); } /** @@ -593,14 +593,15 @@ * components have been added. */ protected void repaintFix() { + SwingUtilities.invokeIn(new Runnable() { public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) { - peer.layout(true); - } + if (hasPeer()) + ((Shell) peer).layout(true); + SwingUtilities.invokeIn(new Runnable() { public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) { + if (hasPeer()) { // This is an interesting GTK bug - sometimes the size is // reported as < 40, the peer doesn't paint or layout @@ -624,32 +625,57 @@ }, 10); } - public Control getSWTPeer() { return peer; } - public void setSwingWTParent(Composite parent) throws Exception { throw new Exception("Window can't have parent."); } - public final void setAlwaysOnTop(boolean alwaysOnTop) throws SecurityException - { - toFront(); + public Control getSWTPeer() { + return peer; + } + + public void setSwingWTParent(Composite parent) throws Exception { + throw new Exception("Window can't have parent."); + } + + public final void setAlwaysOnTop(boolean alwaysOnTop) + throws SecurityException { + toFront(); + } + + public swingwt.awt.Component getFocusOwner() { + return SwingWTUtils.getFocusedComponent(); + } + + public Window getOwner() { + Window win = null; + try { + if (this.parent != null) { + if (parent instanceof Window) + win = (Window) parent; + } + } catch (Exception e) { + } + return win; + } + + public Component findComponentAt(int x, int y) { + return rootPane.findComponentAt(x, y); + } + + /* + public Window(Shell peer) { + this.peer = peer; } - public swingwt.awt.Component getFocusOwner() - { - return SwingWTUtils.getFocusedComponent(); + + public Window[] getOwnedWindows() { + final java.util.List windows = new ArrayList(); + SwingUtilities.invokeSync(new Runnable() { + public void run() { + //org.eclipse.swt.widgets.Dialog[] dialogs = + Shell[] dialogs = peer.getShells(); + for (int i = 0; i < dialogs.length; i++) + windows.add(new Window(dialogs[i])); + + } + }); + return windows.toArray(new Window[windows.size()]); } - public Window getOwner() - { - Window win = null; - try - { - if (this.parent!=null) - { - if (parent instanceof Window) - win = (Window)parent; - } - } - catch(Exception e) - { - } - return win; - } - + */ } Index: src/swingwt/awt/LayoutManager.java =================================================================== --- src/swingwt/awt/LayoutManager.java (revision 85) +++ src/swingwt/awt/LayoutManager.java (working copy) @@ -12,13 +12,50 @@ package swingwt.awt; /** -* @author Daniel Spiewak + * Layout managers describe how components are positioned in containers. + * + * @author Daniel Spiewak + * @author Thiago Tonelli Bartolomei */ public interface LayoutManager { - void addLayoutComponent(String name, Component comp); - void removeLayoutComponent(Component comp); - Dimension preferredLayoutSize(Container parent); - Dimension minimumLayoutSize(Container parent); - void layoutContainer(Container parent); + /** + * Adds the component to this layout, identifying it by this string. + * + * @param name + * @param component + */ + public void addLayoutComponent(String name, Component component); + + /** + * Removes the component from this layout. + * + * @param component + */ + public void removeLayoutComponent(Component component); + + /** + * Computes the size this container should have based on the + * components contained in it. + * + * @param container + * @return + */ + public Dimension preferredLayoutSize(Container container); + + /** + * Computes the minimum size of this container, based on the + * components contained in it. + * + * @param container + * @return + */ + public Dimension minimumLayoutSize(Container container); + + /** + * Lays out the container. + * + * @param container + */ + public void layoutContainer(Container container); } Index: src/swingwt/awt/LayoutManager2.java =================================================================== --- src/swingwt/awt/LayoutManager2.java (revision 85) +++ src/swingwt/awt/LayoutManager2.java (working copy) @@ -12,13 +12,57 @@ package swingwt.awt; /** - * @author Daniel Spiewak + * An extension to the basic layout manager that allows components + * to be added with constraint objects. + * + * @author Daniel Spiewak + * @author Thiago Tonelli Bartolomei */ public interface LayoutManager2 extends LayoutManager { - void addLayoutComponent(Component comp, Object constraints); - public Dimension maximumLayoutSize(Container target); - public float getLayoutAlignmentX(Container target); - public float getLayoutAlignmentY(Container target); - public void invalidateLayout(Container target); + /** + * Adds this component to the manager with this corresponding + * constraint object. + * + * @param component + * @param constraints + */ + public void addLayoutComponent(Component component, Object constraints); + + /** + * Computes the maximum size of this container, based on the + * components in it. + * + * @param container + * @return + */ + public Dimension maximumLayoutSize(Container container); + + /** + * A value between 0 (origin) and 1 (infinite) that specifies the + * position this container should be aligned with respect to other + * components, in the X axis. Note that 0.5 means center. + * + * @param container + * @return + */ + public float getLayoutAlignmentX(Container container); + + /** + * A value between 0 (origin) and 1 (infinite) that specifies the + * position this container should be aligned with respect to other + * components, in the Y axis. Note that 0.5 means center + * + * @param container + * @return + */ + public float getLayoutAlignmentY(Container container); + + /** + * The layout manager should invalidate the layout, i.e., it + * should dischard any cached information. + * + * @param container + */ + public void invalidateLayout(Container container); } Index: src/swingwt/awt/Dialog.java =================================================================== --- src/swingwt/awt/Dialog.java (revision 85) +++ src/swingwt/awt/Dialog.java (working copy) @@ -16,6 +16,7 @@ import swingwtx.swing.*; import org.eclipse.swt.*; +import org.eclipse.swt.widgets.Shell; public class Dialog extends Window { @@ -59,44 +60,54 @@ //override to make initial settings for a modal dialog } - /** Overridden from Window to force private events dispatching for modality */ - public void setVisible(final boolean b) { - final Dialog me = this; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (b) { - if (!SwingWTUtils.isSWTControlAvailable(peer)) - create(); - - // Display the peer - peer.open(); + /** + * Overridden from Window to force private events dispatching for modality + */ + public void setVisible(final boolean visible) { + + if (visible) { + // note that create() will be executed in a sync call so it does not have + // to be inside the subsequent invokeSync + if (! hasPeer()) + create(); + + SwingUtilities.invokeSync(new Runnable() { + public void run() { + // Display the peer + ((Shell) peer).open(); - // Assign focus - peer.setFocus(); - - // Make sure it displays ok - repaintFix(); - - // Overridable initial settings - initDialog(); - - // If it's a modal dialog, run an event loop - // to cause blocking. The nice thing is this works - // even if you're called on the existing dispatch thread. - if (isModal) dispatchEvents(); - - } - else { - // If the Window is already closing because the user hit the x - // button, don't do anything - if (isClosed) return; - if (SwingWTUtils.isSWTControlAvailable(peer)) - peer.close(); - } - } - }); - - } - public void setUndecorated(boolean undecorated){} + // Assign focus + peer.setFocus(); -} + // Make sure it displays ok + repaintFix(); + + // Overridable initial settings + initDialog(); + + // If it's a modal dialog, run an event loop + // to cause blocking. The nice thing is this works + // even if you're called on the existing dispatch thread. + if (isModal) + dispatchEvents(); + } + }); + + } else { + // If the Window is already closing because the user hit the + // X button, don't do anything + if (isClosed) + return; + + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + ((Shell) peer).close(); + } + }); + } + } + + public void setUndecorated(boolean undecorated) { + } +} \ No newline at end of file Index: src/swingwt/awt/BasicStroke.java =================================================================== --- src/swingwt/awt/BasicStroke.java (revision 85) +++ src/swingwt/awt/BasicStroke.java (working copy) @@ -37,6 +37,18 @@ this.dash_phase = dash_phase; } + /** + * TODO Comment!! + * + * @param f + * @param capButt + * @param joinRound + * @param g + */ + public BasicStroke(float f, int capButt, int joinRound, float g) { + // TODO Auto-generated constructor stub + } + public Shape createStrokedShape(Shape p) { // I don't really know what to do here. If we are letting swt handle // all the stroking when it draws the path, how are we going to return Index: src/swingwt/awt/SWTGraphics2DRenderer.java =================================================================== --- src/swingwt/awt/SWTGraphics2DRenderer.java (revision 85) +++ src/swingwt/awt/SWTGraphics2DRenderer.java (working copy) @@ -12,6 +12,8 @@ package swingwt.awt; +import java.util.Map; + import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Path; @@ -22,11 +24,11 @@ import swingwt.awt.geom.AffineTransform; import swingwt.awt.geom.PathIterator; import swingwt.awt.geom.SWTPathIterator; -import swingwt.awt.image.*; +import swingwt.awt.image.BufferedImage; +import swingwt.awt.image.BufferedImageOp; +import swingwt.awt.image.ImageObserver; import swingwtx.swing.SwingWTUtils; -import java.util.Map; - /** * This class is the final point for the mapped AWT graphics stuff - it * provides the rendering capabilities to the Graphics/Graphics2D classes @@ -143,6 +145,22 @@ }); } + /** + * + * TODO Comment!! + * + * @param img + * @param op + * @param x + * @param y + */ + public void drawImage(BufferedImage img, + BufferedImageOp op, + int x, + int y) { + + } + public boolean drawImage(final swingwt.awt.Image img, final int x, final int y, final Color bgcolor, final ImageObserver observer) { swingwtx.swing.SwingUtilities.invokeSync(new Runnable() { public void run() { Index: src/swingwt/awt/Container.java =================================================================== --- src/swingwt/awt/Container.java (revision 85) +++ src/swingwt/awt/Container.java (working copy) @@ -13,12 +13,19 @@ package swingwt.awt; -import org.eclipse.swt.widgets.*; -import org.eclipse.swt.*; +import java.util.Locale; +import java.util.Set; +import java.util.Vector; -import swingwtx.swing.*; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Listener; -import java.util.*; +import swingwtx.accessibility.Accessible; +import swingwtx.accessibility.AccessibleContext; +import swingwtx.accessibility.AccessibleRole; +import swingwtx.accessibility.AccessibleStateSet; +import swingwtx.swing.SwingUtilities; +import swingwtx.swing.SwingWTUtils; /** * Any component that can contain other components. @@ -29,102 +36,199 @@ /** The SWT peer this container represents */ public org.eclipse.swt.widgets.Composite composite = null; - /** The layout manager being used to position child components */ + /** + * The layout manager being used to position child components. + * + * Code should never refer directly to this field; getLayout() should + * be used instead, because it allows sub-types to use other implementations. + */ protected LayoutManager layout = null; - protected boolean layoutListenerAdded; + /** + * Flag indicates that the container already hooked up with the composite + * to get resize events. + */ + protected boolean layoutListenerAdded = false; + /** Cache of components waiting to be laid out */ protected Vector comps = new Vector(); protected Vector containerListeners = new Vector(); - public Dimension getMinimumSize() { - if (layout == null || isMinimumSizeSet()) - return super.getMinimumSize(); - return layout.minimumLayoutSize(this); - } + + // SIZE AND POSITIONING + + /** + * Overrides to, if available, compute the minimum size using + * the layout manager for this container (unless the user set + * a minimum size value). + * + * @return + */ + //@Override + public Dimension getMinimumSize() { + LayoutManager l = getLayout(); + + if (null == l || isMinimumSizeSet()) + return super.getMinimumSize(); + + return l.minimumLayoutSize(this); + } - public Dimension minimumSize() { return getMinimumSize(); } - public Dimension preferredSize() { return getPreferredSize(); } + /** + * Overrides to, if available, compute the preferred size using + * the layout manager for this container (unless the user set + * a preferred size value). + * + * @return + */ + //@Override + public Dimension getPreferredSize() { + LayoutManager l = getLayout(); + + if (null == l || isPreferredSizeSet()) + return super.getPreferredSize(); + + return l.preferredLayoutSize(this); + } - public Dimension getPreferredSize() { - if (layout == null || isPreferredSizeSet()) - return super.getPreferredSize(); - return layout.preferredLayoutSize(this); - } + /** + * Overrides to, if available, compute the preferred size using + * the layout manager for this container. + * + * @return + */ + //@Override + protected Dimension computePreferredSize() { + LayoutManager l = getLayout(); + + if (null == l || null == getComposite()) + return super.computePreferredSize(); - public Dimension getMaximumSize() { - if (isMaximumSizeSet() || !(layout instanceof LayoutManager2)) - return super.getMaximumSize(); - return ((LayoutManager2)layout).maximumLayoutSize(this); - } + return l.preferredLayoutSize(this); + } + + /** + * Overrides to, if available, compute the maximum size using + * the layout manager for this container (unless the user set + * a maximum size value). + * + * @return + */ + //@Override + public Dimension getMaximumSize() { + LayoutManager l = getLayout(); + + // only LayoutManager2 can compute the maximum size + if (null == l || isMaximumSizeSet() || ! (l instanceof LayoutManager2)) + return super.getMaximumSize(); + + return ((LayoutManager2) l).maximumLayoutSize(this); + } - protected Dimension computePreferredSize() { - if (getComposite() == null || getLayout() == null) - return super.computePreferredSize(); - - return getLayout().preferredLayoutSize(this); + /** + * Returns the layout used by this container. + * + * Some sub-types may want to override this if a different layout is to + * be used (e.g., for views or internal frames). + */ + public LayoutManager getLayout() { + return layout; } - - public void addContainerListener(swingwt.awt.event.ContainerListener l) { - containerListeners.add(l); + + /** + * Adds an existing component to the layout manager + * + * This is not part of AWT's API! + */ + public void addComponentToLayout(Component c) { + LayoutManager l = getLayout(); + + if (null != l) { + if (l instanceof LayoutManager2) { + ((LayoutManager2) l).addLayoutComponent(c, c.layoutModifier); + } else { + l.addLayoutComponent(c.getName(), c); + } + } } - - public void removeContainerListener(swingwt.awt.event.ContainerListener l) { - containerListeners.remove(l); + + /** + * Forces laying out of this container's child components again. + */ + //@Override + public void invalidateImpl() { + // Note that here we do not want to use getLayout() because that would + // probably cause an infinite loop... + if (null != layout && SwingWTUtils.isSWTControlAvailable(composite)) { + if (layout instanceof LayoutManager2) + ((LayoutManager2) layout).invalidateLayout(this); + + layout.layoutContainer(this); + } } - - public Component add(Component c) { - return doAdd(c); + + /** + * I'm totally re-writing this method. No longer + * will it only mirror the layouts. From now on, + * it will actually use the layout managers to layout + * the component, not the mirrored SWT layouts. + * Two big advantages with this approach. (a) It + * allows custom layout managers. (b) It means + * less work since we don't have to port anything. + * (yea!) + * + * @author Daniel Spiewak + */ + public void setLayout(LayoutManager l) { + setLayoutImpl(l); } - - public Component add(Component c, int index) { - return add(c); - } - /** Actually does the hard work of adding something to a container */ - public Component doAdd(final Component c) { + /** + * The actual code that handles assignment of the + * layout manager. + * + * Separated out as setLayout will often get + * subclassed and my head will explode if I don't + * do something like this :-) + */ + protected void setLayoutImpl(LayoutManager l) { + layout = l; - if (c == null) return null; - final Container me = this; + if (composite == null || layoutListenerAdded) + return; - // Don't add it to the cache again if this component is already cached - // - this stops us adding the same component twice. - if (comps.indexOf(c) == -1) { - comps.add(c); - // Register the comonent with the layout if needed - addComponentToLayout(c); - } - - // Cache us with the child component - this is just so that - // the hierarchy is visible before the peers are realised - c.parent = this; - - if (!SwingWTUtils.isSWTControlAvailable(composite)) return c; - - // Ensure that the setSwingWTParent calls are on the dispatch - // thread as they go down - object creation should always be - // on this thread + layoutListenerAdded = true; SwingUtilities.invokeSync(new Runnable() { public void run() { - try { - c.setSwingWTParent(me); - c.setCachedProperties(); - c.registerEvents(); - processContainerEvent(new swingwt.awt.event.ContainerEvent(me, swingwt.awt.event.ContainerEvent.COMPONENT_ADDED, c)); - } - catch (Exception e) { - e.printStackTrace(); - } + // we don't want an SWT layout since we will control the layout ourselves + composite.setLayout(null); - queuedValidate(); - + // add a resize listener to let us know when to invalidate the layout + composite.addListener(SWT.Resize, new Listener() { + public void handleEvent(org.eclipse.swt.widgets.Event e) { + invalidate(); + } + }); } }); - return c; } + + /* + public void setBounds(int x, int y, int width, int height) { + super.setBounds(x, y, width, height); + + SwingUtilities.invokeSync(new Runnable() { + public void run() { + invalidateImpl(); + } + }); + }*/ + + // LISTENERS AND EVENTS + protected void processEvent(AWTEvent e) { // Can't think of any reason for this to be here other than compile compat } @@ -139,34 +243,14 @@ } } - /** - * Adds an existing component to the layout manager - */ - public void addComponentToLayout(Component c) { - if (layout != null) { - if (layout instanceof LayoutManager2) { - ((LayoutManager2)layout).addLayoutComponent(c, c.layoutModifier); - } - else - layout.addLayoutComponent(c.getName(), c); - } + public void addContainerListener(swingwt.awt.event.ContainerListener l) { + containerListeners.add(l); } - /** Forces laying out of this container's child components again. */ - public void invalidateImpl() { - if (layout != null && SwingWTUtils.isSWTControlAvailable(composite)) { - layout.layoutContainer(this); - } + public void removeContainerListener(swingwt.awt.event.ContainerListener l) { + containerListeners.remove(l); } - public void setBounds(int x, int y, int width, int height) { - super.setBounds(x, y, width, height); - SwingUtilities.invokeSync(new Runnable() { - public void run() { - invalidateImpl(); - } - }); - } /** Forces laying out of this container's child components again. */ public void doLayout() { invalidate(); } @@ -175,7 +259,9 @@ //Stubbed protected void validateTree() {} /** Forces laying out of this container's child components again. */ - public void revalidate() { invalidate(); } + public void revalidate() { + invalidate(); + } /** * Attempts to ensure that a request to layout a container is only @@ -207,11 +293,13 @@ * Addition for layouts requiring object based modifiers */ public void add(swingwt.awt.Component c, Object layoutModifier) { - if (c == null) return; + if (c == null) + return; + c.layoutModifier = layoutModifier; if (layoutModifier instanceof String) - layout.addLayoutComponent((String)layoutModifier, c); + getLayout().addLayoutComponent((String)layoutModifier, c); doAdd(c); } @@ -256,7 +344,12 @@ private void removeImpl(swingwt.awt.Component c) { comps.remove(c); - if (layout != null) layout.removeLayoutComponent(c); + + LayoutManager l = getLayout(); + + if (null != l) + l.removeLayoutComponent(c); + c.componentOnlyDispose(); c.setComponentRemoved(); processContainerEvent(new swingwt.awt.event.ContainerEvent(this, swingwt.awt.event.ContainerEvent.COMPONENT_REMOVED, c)); @@ -280,64 +373,79 @@ comps.remove(c); } - /** Returns the layout used by this container */ - public LayoutManager getLayout() { - return layout; + + /** Returns the SWT peer being used for this container */ + public org.eclipse.swt.widgets.Composite getComposite() { + return composite; } - /** - * I'm totally re-writing this method. No longer - * will it only mirror the layouts. From now on, - * it will actually use the layout managers to layout - * the component, not the mirrored SWT layouts. - * Two big advantages with this approach. (a) It - * allows custom layout managers. (b) It means - * less work since we don't have to port anything. - * (yea!) - * - * @author Daniel Spiewak - */ - public void setLayout(LayoutManager l) { - setLayoutImpl(l); + + public ComponentOrientation getComponentOrientation() { + return ComponentOrientation.getOrientation(Locale.getDefault()); } - /** - * The actual code that handles assignment of the - * layout manager. - * - * Separated out as setLayout will often get - * subclassed and my head will explode if I don't - * do something like this :-) - */ - protected void setLayoutImpl(LayoutManager l) { - layout = l; + public Insets getInsets() { + return new Insets(0,0,0,0); + } - if (composite == null || layoutListenerAdded) - return; + + // COMPONENT HIERARCHY + - layoutListenerAdded = true; + public Component add(Component c) { + return doAdd(c); + } + + public Component add(Component c, int index) { + return add(c); + } + + /** Actually does the hard work of adding something to a container */ + public Component doAdd(final Component c) { + + if (c == null) return null; + final Container me = this; + + // Don't add it to the cache again if this component is already cached + // - this stops us adding the same component twice. + if (comps.indexOf(c) == -1) { + comps.add(c); + // Register the comonent with the layout if needed + addComponentToLayout(c); + } + + // Cache us with the child component - this is just so that + // the hierarchy is visible before the peers are realised + c.parent = this; + + if (! SwingWTUtils.isSWTControlAvailable(composite)) + return c; + + // Ensure that the setSwingWTParent calls are on the dispatch + // thread as they go down - object creation should always be + // on this thread SwingUtilities.invokeSync(new Runnable() { public void run() { - // we don't want an SWT layout since we will control the layout ourselves - composite.setLayout(null); + try { + c.setSwingWTParent(me); + c.assertCachedProperties(); + c.registerEvents(); + processContainerEvent(new swingwt.awt.event.ContainerEvent(me, swingwt.awt.event.ContainerEvent.COMPONENT_ADDED, c)); + } + catch (Exception e) { + e.printStackTrace(); + } - // add a resize listener to let us know when to invalidate the layout - composite.addListener(SWT.Resize, new Listener() { - public void handleEvent(org.eclipse.swt.widgets.Event e) { - invalidate(); - } - }); - + // avoid computing validation while building the GUI + if (getParent().isVisible()) + queuedValidate(); } }); + return c; } - /** Returns the SWT peer being used for this container */ - public org.eclipse.swt.widgets.Composite getComposite() { - return composite; - } - + public Container getParent() { return parent; } @@ -348,8 +456,7 @@ * "composite" variable */ public void setSwingWTParent(swingwt.awt.Container parent) throws Exception { - if (layout != null) - setLayoutImpl(layout); + setLayoutImpl(getLayout()); if (comps.size() > 0) { Object[] obs = comps.toArray(); @@ -359,15 +466,7 @@ } } } - - public ComponentOrientation getComponentOrientation() { - return ComponentOrientation.getOrientation(Locale.getDefault()); - } - - public Insets getInsets() { - return new Insets(0,0,0,0); - } - + public int getComponentCount() { return comps.size(); } @@ -387,47 +486,159 @@ } return cps; } - + /** - * Useful for debugging purposes. Shows this container and - * all it's children. + * Tries to find the most specific component in this container which + * contains the point with coordinates x and y. + * + * @param x + * @param y + * @return null, if this container does not contain this point, or the + * most specific component that contains the point (i.e., it can be a + * child of this container). + * */ - public void debug_showContainmentTree() { - System.out.println("Containment Tree: ===================="); - System.out.println(getClass().getName()); - xdebug_showChildren(this, 1); + public Component findComponentAt(int x, int y) { + if (! this.contains(x, y)) { + return null; + } + Component[] cps = this.getComponents(); + for (int i = 0; i < cps.length; i ++) { + Component c = cps[i]; + if (c.contains(x, y)) { + if (c instanceof Container) { + return ((Container) c).findComponentAt(x, y); + } else { + // the last component + return c; + } + } + } + return this; } - private void xdebug_showChildren(Container c, int level) { - final String SPACE = " "; - for (int i = 0; i < c.comps.size(); i++) { - Component d = (Component) c.comps.get(i); - System.out.println(SPACE.substring(0, level) + d.getClass().getName()); - if (d instanceof Container) - xdebug_showChildren((Container) d, level+1); - } - } - //TODO: implement this - // public Set getFocusTraversalKeys(int id) 1.5 - public Set getFocusTraversalKeys(int id) - { - return null; - - } - //TODO: implement this - // setFocusTraversalKeys(int id, Set keystrokes) 1.5 - public void getFocusTraversalKeys(int id, Set keyStrokes) - { - - - } - public void setFocusTraversalPolicy(FocusTraversalPolicy policy) - { - - - } - public FocusTraversalPolicy getFocusTraversalPolicy() - { - return null; - } + + // FOCUS SUPPORT + + // public Set getFocusTraversalKeys(int id) 1.5 + public Set getFocusTraversalKeys(int id) { + // TODO: implement this + return null; + } + + // setFocusTraversalKeys(int id, Set keystrokes) 1.5 + public void getFocusTraversalKeys(int id, Set keyStrokes) { + // TODO: implement this + } + + public void setFocusTraversalPolicy(FocusTraversalPolicy policy) { + // TODO: implement this + } + + public FocusTraversalPolicy getFocusTraversalPolicy() { + // TODO: implement this + return null; + } + + + // ACCESSIBILITY + + /** + * Sub-types should override this method to create the appropriate + * accessible context for the object. + * + * @return a newly created accessible context + */ + protected AccessibleContext createAccessibleContext() { + return new AccessibleAWTContainer(); + } + + /** + * + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ + protected class AccessibleAWTContainer extends AccessibleAWTComponent { + + /** + * TODO Comment!! + * + * @return + */ + public int getAccessibleIndexInParent() { + return 0; + } + + /** + * TODO Comment!! + * + * @return + */ + public int getAccessibleChildrenCount() { + return 0; + } + + /** + * TODO Comment!! + * + * @param i + * @return + */ + public Accessible getAccessibleChild(int i) { + return null; + } + + /** + * TODO Comment!! + * + * @return + * @throws IllegalComponentStateException + */ + public Locale getLocale() throws IllegalComponentStateException { + return null; + } + + /** + * TODO Comment!! + * + * @return + */ + public AccessibleRole getAccessibleRole() { + return null; + } + + /** + * TODO Comment!! + * + * @return + */ + public AccessibleStateSet getAccessibleStateSet() { + return null; + } + } + + // DEBUG SUPPORT + + /** + * Useful for debugging purposes. Shows this container and all it's + * children. + */ + public void debug_showContainmentTree() { + System.out.println("Containment Tree: ===================="); + System.out.println(debugId() + " bounds->" + getBounds().debugId() + " pref->" + getPreferredSize().debugId()); + xdebug_showChildren(this, 1); + } + + private void xdebug_showChildren(Container c, int level) { + final String SPACE = " "; + for (int i = 0; i < c.comps.size(); i++) { + Component d = (Component) c.comps.get(i); + System.out.println(SPACE.substring(0, level * 2) + d.debugId() + " bounds->" + d.getBounds().debugId() + " pref->" + d.getPreferredSize().debugId()); + + if (d instanceof Container) + xdebug_showChildren((Container) d, level + 1); + } + } + } Index: src/swingwt/awt/Component.java =================================================================== --- src/swingwt/awt/Component.java (revision 85) +++ src/swingwt/awt/Component.java (working copy) @@ -11,30 +11,55 @@ package swingwt.awt; -import org.eclipse.swt.widgets.*; -import org.eclipse.swt.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.util.Locale; +import java.util.Set; +import java.util.Vector; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.custom.ExtendedModifyEvent; +import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.custom.ExtendedModifyEvent; -import org.eclipse.swt.custom.CCombo; -import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Text; import swingwt.awt.dnd.DropTarget; +import swingwt.awt.event.ActionEvent; +import swingwt.awt.event.ActionListener; +import swingwt.awt.event.ComponentEvent; +import swingwt.awt.event.ComponentListener; +import swingwt.awt.event.EventListener; +import swingwt.awt.event.FocusEvent; +import swingwt.awt.event.FocusListener; +import swingwt.awt.event.HierarchyListener; +import swingwt.awt.event.InputMethodEvent; +import swingwt.awt.event.InputMethodListener; +import swingwt.awt.event.KeyEvent; +import swingwt.awt.event.KeyListener; +import swingwt.awt.event.MouseEvent; +import swingwt.awt.event.MouseListener; +import swingwt.awt.event.MouseMotionListener; +import swingwt.awt.event.MouseWheelEvent; +import swingwt.awt.event.MouseWheelListener; import swingwt.awt.font.TextHitInfo; -import swingwt.awt.image.*; +import swingwt.awt.image.ImageObserver; import swingwt.awt.peer.ComponentPeer; -import swingwt.awt.event.*; -import swingwt.awt.event.EventListener; -import swingwtx.accessibility.*; -import swingwtx.swing.*; +import swingwtx.accessibility.AccessibleContext; +import swingwtx.swing.JEditorPane; +import swingwtx.swing.JScrollPane; +import swingwtx.swing.JTable; +import swingwtx.swing.JTextArea; +import swingwtx.swing.JTree; +import swingwtx.swing.SwingUtilities; +import swingwtx.swing.SwingUtilities.SwingWTRunnable; +import swingwtx.swing.SwingWTUtils; -import java.util.*; -import java.text.AttributedCharacterIterator; -import java.text.AttributedString; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - /** * * Tag class for AWT compatibility - subclass JSWTComponent has all the good @@ -53,7 +78,7 @@ protected org.eclipse.swt.widgets.Composite ppeer = null; /** The name of this component */ - protected String componentName = this.getClass().getName(); + protected String componentName = this.getClass().getSimpleName(); /** The graphics configuration */ protected static GraphicsConfiguration graphicsConfig = new GraphicsConfiguration(); @@ -103,8 +128,7 @@ protected Object pLayoutData = null; /** Cache value */ - protected swingwt.awt.Cursor pCursor = swingwt.awt.Cursor - .getPredefinedCursor(swingwt.awt.Cursor.DEFAULT_CURSOR); + protected Cursor pCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); /** * Whether paint events give direct access to component or use an image @@ -165,11 +189,6 @@ /** Whether this component can get the focus */ protected boolean focusable = true; - /** Thread safe object for returning values */ - private Object retval = null; - - private int iretval = 0; - /** Default adapter for Action Events */ protected org.eclipse.swt.events.MouseListener swingWTDefaultActionEventAdapter = null; @@ -196,8 +215,6 @@ public static final float RIGHT_ALIGNMENT = 1.0f; - private boolean retBol; - /** Override in subclasses to paint on the component */ public void paint(Graphics g) { } @@ -262,38 +279,41 @@ /** Change the visibility of the component */ public void setVisible(final boolean b) { pVisible = b; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) + + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { peer.setVisible(b); - } - }); + } + }); } /** Returns true if the component is visible */ public boolean isVisible() { + if (hasPeer()) + return ((Boolean) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return Boolean.valueOf(peer.isVisible()); + } + })).booleanValue(); return pVisible; } /** Returns true if the component is visible */ public boolean isShowing() { - return isVisible(); + return isVisible(); // && null != peer && peer.isVisible(); } - public boolean isFocusOwner() - { - retBol = false; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) - retBol = peer.isFocusControl(); - else - { - - } - } - }); - return retBol; + + public boolean isFocusOwner() { + if (hasPeer()) + return ((Boolean) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return Boolean.valueOf(peer.isFocusControl()); + } + })).booleanValue(); + + return false; } /** @@ -334,12 +354,13 @@ /** Change the enabled state of the component */ public void setEnabled(final boolean b) { pEnabled = b; - SwingUtilities.invokeAsync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) + + if (hasPeer()) + SwingUtilities.invokeAsync(new Runnable() { + public void run() { peer.setEnabled(b); - } - }); + } + }); } /** Returns true if the component is enabled */ @@ -349,22 +370,22 @@ /** Requests the component receives the focus */ public void requestFocus() { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { peer.setFocus(); - } - }); + } + }); } /** Forces keyboard focus to the component */ public void grabFocus() { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { peer.forceFocus(); - } - }); + } + }); } public DropTarget getDropTarget() { @@ -386,9 +407,9 @@ /** Redraws the component */ public void repaint() { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) { + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { // If this component is drawable peer (ie. has // no descendant overriding it), then we assume the // developer @@ -402,9 +423,10 @@ peer.redraw(); } } - } - }); + }); } + + // COLORS /** Returns true if the background was explicitly set */ public boolean isBackgroundSet() { @@ -426,13 +448,12 @@ } protected void updatePeerBackground() { - if (SwingWTUtils.isSWTControlAvailable(peer)) { + if (hasPeer()) SwingUtilities.invokeSync(new Runnable() { public void run() { updatePeerBackgroundSWT(); } }); - } } /** Returns the background colour of the component */ @@ -448,99 +469,548 @@ /** Returns the foreground colour of the component */ public swingwt.awt.Color getForeground() { - if (!SwingWTUtils.isSWTControlAvailable(peer)) { - if (pForeground == null) { - return Color.BLACK; - } else { - return pForeground; - } - } else { + if (hasPeer()) + return (Color) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return new Color(peer.getForeground()); + } + }); + + if (null == pForeground) + return Color.BLACK; + + return pForeground; + } + + /** Sets the foreground colour of the component */ + public void setForeground(final swingwt.awt.Color c) { + pForeground = c; + + if (hasPeer()) SwingUtilities.invokeSync(new Runnable() { public void run() { - retval = new swingwt.awt.Color(peer.getForeground()); + peer.setForeground(c.getSWTColor()); } }); - return (Color) retval; + } + + /** + * Return a graphics context for drawing on this object. Note that only + * instances of JComponent are allowed + */ + public Graphics getGraphics() { + if (hasPeer()) + return (Graphics) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return new SWTGraphics2DRenderer( + new org.eclipse.swt.graphics.GC(peer), true); + } + }); + return null; + } + + + + // SIZES AND POSITIONING + + /** + * Returns the size of the peer. + * + * The value comes directly from the peer if it has been realized, or it + * is computed from the cached size value. + * + * Not part of AWT's API! + * + * @return + */ + public Dimension getPeerSize() { + if (hasPeer()) + return (Dimension) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return new Dimension(peer.getSize()); + } + }); + + // No peer, compute size... + if (pSize != null) + return (Dimension) pSize.clone(); + + return new Dimension(); + } + + /** + * Returns the bounds of the peer. + * + * The value comes directly from the peer if it has been realized, or it + * is computed from the cached location and size values. + * + * Not part of AWT's API! + * + * @return + */ + protected final Rectangle getPeerBounds() { + if (hasPeer()) + return (Rectangle) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return new Rectangle(peer.getLocation(), peer.getSize()); + } + }); + + // No peer, compute bounds... + Rectangle rect = new Rectangle(0, 0, 0, 0); + if (pLocation != null) + rect.setLocation(pLocation); + + if (pSize != null) + rect.setSize(pSize); + + return rect; + } + + /** + * Directly sets the bounds of the peer. + * + * This method assumes that the peer exists and that it is executed in the SWT thread. + * + * @param x + * @param y + * @param width + * @param height + */ + protected final void setPeerBounds(int x, int y, int width, int height) { + //assert(null != peer); + cachedComputedPreferredSize = null; + peer.setBounds(x, y, width, height); + } + + /** + * Returns the size of this component. + * + * If the component is embedded inside a JScrollPane component, the larger of + * the preferredSize/peers actual size. This works rather nicely for + * handling layouts inside a scrollbar as we can simply offset a large + * composite according to the scrollbar positions inside JScrollPane. + * + * One note - if the component is JTree, JTable, JTextArea or JEditorPane, + * then we return the size as usual since these components handle their own + * scrolling and we don't want the JScrollPane behaving weirdly. + * + * @return {@link #getPeerSize()}, unless the component is embedded into a + * JScrollPane component, in which case a larger area may be returned. + * @see #getPeerSize() + * @see #getPreferredSize() + */ + public Dimension getSize() { + + if (parent instanceof JScrollPane + && (! (this instanceof JTable)) + && (! (this instanceof JTextArea)) + && (!(this instanceof JTree)) + && (! (this instanceof JEditorPane))) { + + Dimension returnDim = getPreferredSize(); + Dimension peers = getPeerSize(); + + // Get max between preferred and peer sizes + if (returnDim.width < peers.width) + returnDim.width = peers.width; + if (returnDim.height < peers.height) + returnDim.height = peers.height; + + return returnDim; + + } else { + + return getPeerSize(); } } - /** Sets the foreground colour of the component */ - public void setForeground(final swingwt.awt.Color c) { - if (!SwingWTUtils.isSWTControlAvailable(peer)) - pForeground = c; - else + /** + * Overloaded version of getSize() that uses the passed in dimension to put + * the size in to prevent allocation of another on the heap. + * + * NB: Still creates a new dimension due to how SwingWT works so there is no + * benefit to using this method. + * + * @Deprecated we should remove this method because it does not make much sense... + */ + public Dimension getSize(Dimension toFill) { + Dimension d = getSize(); + toFill.width = d.width; + toFill.height = d.height; + return toFill; + } + + /** + * Simply returns {@link #getSize()}. + * + * @see #getSize() + */ + public Dimension size() { + return getSize(); + } + + /** + * Sets the actual size of the peer. + * + * This method interprets a value of -1 to mean "the current value". + * + * @param width + * @param height + */ + public void setSize(final int width, final int height) { + setSize(new Dimension(width, height)); + } + + /** + * Sets the actual size of the peer. + * + * This method interprets a value of -1 in width or height to mean "the current value". + * + * @param d + */ + public void setSize(final Dimension d) { + pSize = d; + + if (hasPeer()) SwingUtilities.invokeSync(new Runnable() { public void run() { - peer.setForeground(c.getSWTColor()); + cachedComputedPreferredSize = null; + org.eclipse.swt.graphics.Rectangle rec = peer.getBounds(); + + // a value of -1 is interpreted as "do not change the current value" + // This allows for faster setWidth and setHeight + if (d.width != -1) + rec.width = d.width; + if (d.height != -1) + rec.height = d.height; + + // note that peer.setSize would reset the location to 0,0 + peer.setBounds(rec); + /* + * It seems more efficient to call peer.getBounds than to use 2 getLocation() calls + setPeerBounds( + getLocation().x, + getLocation().y, + d.width, + d.height); + */ } }); } - - /** Returns the width of the component */ + + /** + * Returns the width of the component, as calculated by {@link #getSize()}. + * + * @return the component's width + */ public int getWidth() { return getSize().width; } - /** Returns the height of the component */ + /** + * Returns the height of the component, as calculated by {@link #getSize()}. + * + * @return the component's height + */ public int getHeight() { return getSize().height; } - /** Sets the width of the component. */ + /** + * Sets the width of the component. + */ public void setWidth(int width) { - setSize(width, getHeight()); + setSize(width, -1); } - /** Sets the height of the component. */ + /** + * Sets the height of the component. + */ public void setHeight(int height) { setSize(getWidth(), height); } + + /** + * Returns the bounds of the component. + * + * The default implementation of this method simply calls getPeerBounds(), + * which will return the bounds of the peer, if available, or a computed + * value if not. + * + * @see #getPeerBounds() + */ + public Rectangle getBounds() { + return getPeerBounds(); + } + + /** + * Sets the physical bounds of the component. + * + * @param r + * @see #setBounds(int, int, int, int) + */ + public void setBounds(Rectangle r) { + setBounds(r.x, r.y, r.width, r.height); + } + + /** + * Sets the physical bounds of the component. + * + * This method will move the component to the specified location (wrt its parent) and + * will resize it. + * + * @param x + * @param y + * @param width + * @param height + */ + public void setBounds(final int x, final int y, final int width, final int height) { + pSize = new Dimension(width, height); + pLocation = new Point(x, y); + + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + setPeerBounds(x, y, width, height); + } + }); + } + /** - * Return a graphics context for drawing on this object. Note that only - * instances of JComponent are allowed + * Computes the position of this component in the screen. + * + * If the component has not been created yet, the origin is returned. */ - public Graphics getGraphics() { - if (!SwingWTUtils.isSWTControlAvailable(peer)) - return null; - else { - return (Graphics) SwingUtilities - .invokeSyncReturn(new SwingUtilities.Task() { - public Object exec() { - return new SWTGraphics2DRenderer( - new org.eclipse.swt.graphics.GC(peer), true); - } - }); - } + public Point getLocationOnScreen() { + + if (hasPeer()) + return (Point) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + // get location relative to parent + org.eclipse.swt.graphics.Point parent = peer.getLocation(); + // translate from parent to "null", which represents the screen + org.eclipse.swt.graphics.Point l = SwingWTUtils.getDisplay().map(peer.getParent(), null, parent.x, parent.y); + return new Point(l.x, l.y); + } + }); + + return new Point(0, 0); } + /** + * Returns the component's location with respect to its parent. + * + * If the peer is not realized, use cached location or the origin. + */ + public Point getLocation() { + if (hasPeer()) + return (Point) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return new Point(peer.getLocation()); + } + }); + + // No peer, compute location... + if (pLocation != null) + return new Point(pLocation); + + return new Point(); + } + + /** + * Sets the component's location in it's container. + * + * @see #setLocation(Point) + */ + public void setLocation(int x, int y) { + setLocation(new Point(x, y)); + } + + /** + * Sets the component's location in it's container + */ + public void setLocation(final Point p) { + pLocation = p; + + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + cachedComputedPreferredSize = null; + org.eclipse.swt.graphics.Rectangle rec = peer.getBounds(); + + rec.x = p.x; + rec.y = p.y; + + peer.setBounds(rec); + } + }); + } + + /** + * Returns the component's X position in it's parent container. + * + * @see #getLocation() + */ + public int getX() { + return getLocation().x; + } + + /** + * Returns the component's Y position in it's parent container. + * + * @see #getLocation() + */ + public int getY() { + return getLocation().y; + } + + /** + * Causes this component and its parents to be invalidated. + * + * This method will cause all components that are ancestors of this component + * to be invalidated. This means that they will receive a {@link #invalidateImpl()} + * call each, from top to bottom. + */ + public void invalidate() { + cachedComputedPreferredSize = null; + SwingWTUtils.invalidate(this); + } + + /** + * This is called when a sub-component is invalidated. + * + * Container classes should override this method to recompute the layout + * of its children. + */ + public void invalidateImpl() { + } + + /** + * Sets the preferred size of the object for layout purposes. + * + * @param d + */ + public void setPreferredSize(Dimension d) { + pPrefSize = d; + } + + /** + * Checks whether the user set a preferred size to this component. + * + * @return + */ public boolean isPreferredSizeSet() { - return pPrefSize != null; + return null != pPrefSize; } + + /** + * Sets the maximum size of the object for layout purposes. + * + * @param d + */ + public void setMaximumSize(Dimension d) { + pMaxSize = d; + } + + /** + * Checks whether the user set a maximum size to this component. + * + * @return + */ + public boolean isMaximumSizeSet() { + return null != pMaxSize; + } /** + * Returns the maximum size of the component. + * + * This will be the value set by the user as maximum size or + * the current value for {@link #getPreferredSize()}. + * + * @return + */ + public Dimension getMaximumSize() { + if (null == pMaxSize) + return getPreferredSize(); + return pMaxSize; + } + + /** + * Returns the minimum size of the component. + * + * This will be the value set by the user as minimum size or + * the current value for {@link #getPreferredSize()}. + * + * @return + */ + public Dimension getMinimumSize() { + if (null == pMinSize) + return getPreferredSize(); + return pMinSize; + } + + /** + * Deprecated shorthand to {@link #getMinimumSize()}. + * + * @return + */ + public Dimension minimumSize() { + return getMinimumSize(); + } + + /** + * Sets the minimum size of the object for layout purposes. + * + * @param d + */ + public void setMinimumSize(Dimension d) { + pMinSize = d; + } + + /** + * Checks whether the user set a minimum size to this component. + * + * @return + */ + public boolean isMinimumSizeSet() { + return null != pMinSize; + } + + /** + * Deprecated shorthand to {@link #getPreferredSize()}. + * + * @return + */ + public Dimension preferredSize() { + return getPreferredSize(); + } + + /** * Returns the preferred size the component would like to be displayed at - * very important for proper layout managers. * * @author Robin Rawson-Tetley */ public Dimension getPreferredSize() { - - // Since preferred size is fulfilling it's "real" role now, it needs to - // be - // the height the component would prefer to be displayed at. This is - // either + + // Since preferred size is fulfilling it's "real" role now, it needs to be + // the height the component would prefer to be displayed at. This is either // what the user set, or (if not set), a computed estimate // - if (pPrefSize != null) { + if (null != pPrefSize) return pPrefSize; - } else if (SwingWTUtils.isSWTControlAvailable(peer)) { - return getComputedPreferredSize(); - } else { - // The component has not yet been realised, so we are going to - // have to make some guesses based on the type - return calculatePreferredSize(); + + if (hasPeer()) { + if (null == cachedComputedPreferredSize) + cachedComputedPreferredSize = computePreferredSize(); + return cachedComputedPreferredSize; } + + // The component has not yet been realised, so we are going to + // have to make some guesses based on the type + return calculatePreferredSize(); } /** @@ -556,22 +1026,14 @@ * size. */ protected Dimension computePreferredSize() { - org.eclipse.swt.graphics.Point p = peer.computeSize(-1, -1); - return new Dimension(p.x, p.y); + return (Dimension) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + org.eclipse.swt.graphics.Point p = peer.computeSize(-1, -1); + return new Dimension(p.x, p.y); + } + }); } - private Dimension getComputedPreferredSize() { - if (cachedComputedPreferredSize == null) { - cachedComputedPreferredSize = computePreferredSize(); - } - return cachedComputedPreferredSize; - } - - /** Sets the preferred size of the object for layout purposes */ - public void setPreferredSize(Dimension d) { - pPrefSize = d; - } - /** * Override in subclasses to return the preferred size for a given * (non-realised) component. @@ -585,147 +1047,109 @@ */ protected Dimension calculatePreferredSize() { Dimension size = new Dimension(150, 50); - setSize(size); + // Setting the size actually causes a lot of recalculation and loops. It + // does not make sense to do this here. + // TODO we have to experiment with "null layout managers" to see for workarounds + //setSize(size); return size; } - public boolean isMaximumSizeSet() { - return pMaxSize != null; + /** + * Gets a number between 0 and 1 indicating the alignment of this component + * in the X axis of its container. A value of 0.5 means center. + * + * @return + */ + public float getAlignmentX() { + return alignmentX; } - /** Returns the maximum size of the component */ - public Dimension getMaximumSize() { - if (pMaxSize == null) - return getPreferredSize(); - return pMaxSize; + /** + * Gets a number between 0 and 1 indicating the alignment of this component + * in the Y axis of its container. A value of 0.5 means center. + * + * @return + */ + public float getAlignmentY() { + return alignmentY; } - /** Sets the maximum size of the component */ - public void setMaximumSize(Dimension d) { - pMaxSize = d; - } - - public boolean isMinimumSizeSet() { - return pMinSize != null; - } - - /** Returns the minimum size of the component */ - public Dimension getMinimumSize() { - if (pMinSize == null) - return getPreferredSize(); - return pMinSize; - } - - /** Sets the minimum size of the component */ - public void setMinimumSize(Dimension d) { - pMinSize = d; - } - - /** Sets the peer's actual size */ - public void setSize(final int width, final int height) { - setSize(new Dimension(width, height)); - } - - /** Sets the peer's actual size */ - public void setSize(final Dimension d) { - pSize = d; - if (!SwingWTUtils.isSWTControlAvailable(peer)) - return; - - SwingUtilities.invokeSync(new Runnable() { - public void run() { - setPeerBounds(getLocation().x, getLocation().y, - d.width, d.height); - } - }); - } - - public boolean contains(int x, int y) { - return (x >= 0 && y >= 0) && (x < getWidth() && y < getHeight()); - } - - public boolean contains(Point point) { - return contains(point.x, point.y); - } - - public boolean inside(int x, int y) { - return contains(x, y); - } - /** - * Returns the peers actual size. Or, if the peer is embedded inside a - * ScrollPane component, the larger of the preferredSize/peers actual size. - * This works rather nicely for handling layouts inside a scrollbar as we - * can simply offset a large composite according to the scrollbar positions - * inside JScrollPane. + * Sets the value of this component's X alignment. * - * One note - if the component is JTree, JTable, JTextArea or JEditorPane, - * then we return the size as usual since these components handle their own - * scrolling and we don't want the JScrollPane behaving weirdly. + * The value must be between 0 and 1 and will be rounded if needed. + * + * @param val + * @see #getAlignmentX() */ - public Dimension getSize() { - if (parent instanceof JScrollPane && (!(this instanceof JTable)) - && (!(this instanceof JTextArea)) && (!(this instanceof JTree)) - && (!(this instanceof JEditorPane))) { - Dimension returnDim = getPreferredSize(); - Dimension peers = getPeerSize(); - if (returnDim.width < peers.width) - returnDim.width = peers.width; - if (returnDim.height < peers.height) - returnDim.height = peers.height; - return returnDim; - } else - return getPeerSize(); + public void setAlignmentX(float val) { + if (val < 0) + alignmentX = 0; + else if (val > 1) + alignmentX = 1; + else + alignmentX = val; } - /** Calls getSize() */ - public Dimension size() { - return getSize(); + /** + * Sets the value of this component's Y alignment. + * + * The value must be between 0 and 1 and will be rounded if needed. + * + * @param val + * @see #setAlignmentY(float) + */ + public void setAlignmentY(float val) { + if (val < 0) + alignmentY = 0; + else if (val > 1) + alignmentY = 1; + else + alignmentY = val; } - + /** - * Overloaded version of getSize() that uses the passed in dimension to put - * the size in to prevent allocation of another on the heap. + * Checks whether the point identified by (x, y) lies inside this component's area. * - * NB: Still creates a new dimension due to how SwingWT works so there is no - * benefit to using this method. + * Note that x and y are taken with respect to this component's origin (i.e., its + * parent's position). + * + * @param x + * @param y + * @return */ - public Dimension getSize(Dimension rv) { - Dimension d = getSize(); - rv.width = d.width; - rv.height = d.height; - return rv; + public boolean contains(int x, int y) { + Dimension d = this.getSize(); + return (x >= 0 && y >= 0) && (x < d.width && y < d.height); } /** - * Returns the peers actual size, or 0,0 if it hasn't been created yet/is - * invisible + * Checks whether this point is located inside this component. + * + * @param point + * @return + * @see #contains(int, int) */ - public Dimension getPeerSize() { - return getPeerBounds().getSize(); + public boolean contains(Point point) { + return contains(point.x, point.y); } - protected Rectangle getPeerBounds() { - if (!SwingWTUtils.isSWTControlAvailable(peer)) { - Rectangle rect = new Rectangle(0, 0, 0, 0); - if (pLocation != null) { - rect.setLocation(pLocation); - } - if (pSize != null) { - rect.setSize(pSize); - } - return rect; - } - SwingUtilities.invokeSync(new Runnable() { - public void run() { - retval = new Rectangle(peer.getLocation().x, - peer.getLocation().y, peer.getSize().x, - peer.getSize().y); - } - }); - return (Rectangle) retval; + /** + * A deprecated shorthand to {@link #contains(int, int)}. + * + * @param x + * @param y + * @return + */ + public boolean inside(int x, int y) { + return contains(x, y); } - + + // END of SIZE AND POSITIONING + + + + /** FIXME: NOT IMPLEMENTED */ public void setFocusTraversalKeysEnabled(boolean b) { } @@ -734,28 +1158,6 @@ public void setFocusTraversalKeys(int id, Set keystrokes) { } - /** Returns the component's location on screen */ - public Point getLocation() { - return getBounds().getLocation(); - } - - /** - * FIXME: Bad algorithm here, but can't find appropriate routine. - * Display.map() looks interesting, but it is undocumented. - */ - public Point getLocationOnScreen() { - if (!SwingWTUtils.isSWTControlAvailable(peer)) - return new Point(0, 0); - final Point p = getLocation(); - SwingUtilities.invokeSync(new Runnable() { - public void run() { - p.x = p.x + peer.getShell().getLocation().x; - p.y = p.y + peer.getShell().getLocation().y; - } - }); - return p; - } - /** Creates and returns an image */ public Image createImage(int width, int height) { swingwt.awt.image.BufferedImage i = new swingwt.awt.image.BufferedImage( @@ -764,8 +1166,7 @@ } /** Creates and returns a volatile image */ - public swingwt.awt.image.VolatileImage createVolatileImage(int width, - int height) { + public swingwt.awt.image.VolatileImage createVolatileImage(int width, int height) { swingwt.awt.image.VolatileImage i = new swingwt.awt.image.VolatileImage( width, height, swingwt.awt.image.BufferedImage.TYPE_INT_RGB); return i; @@ -778,38 +1179,28 @@ /** Returns the Font used on the component */ public swingwt.awt.Font getFont() { - Font returnFont; - if (!SwingWTUtils.isSWTControlAvailable(peer)) - return pFont; - else { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - retval = new swingwt.awt.Font(peer.getFont()); + if (hasPeer()) + return (Font) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return new Font(peer.getFont()); } }); - returnFont = (swingwt.awt.Font) retval; - } - if (returnFont == null) - returnFont = Font.getStubFont(); - return returnFont; - + //if (returnFont == null) + // returnFont = Font.getStubFont(); + return pFont; } /** Sets the font used by the component */ public void setFont(final swingwt.awt.Font f) { - if (f != null) { - isUserSetFont = true; - if (!SwingWTUtils.isSWTControlAvailable(peer)) - pFont = f; - else - SwingUtilities.invokeSync(new Runnable() { - public void run() { - peer.setFont(f.getSWTFont()); - } - }); - } else { - isUserSetFont = false; - } + this.isUserSetFont = (null != f); + this.pFont = f; + + if (null != f && hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + peer.setFont(f.getSWTFont()); + } + }); } /** @@ -829,100 +1220,39 @@ /** Sets the tooltip text used on the component */ public void setToolTipText(final String text) { pToolTipText = text; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) - peer.setToolTipText(text); - } - }); + + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + peer.setToolTipText(SwingWTUtils.removeHTML(text)); + } + }); } - protected void setPeerBounds(int x, int y, int width, int height) { - cachedComputedPreferredSize = null; - peer.setBounds(x, y, width, height); - } - - /** Sets the physical bounds of the component - used by layout managers */ - public void setBounds(final int x, final int y, final int width, - final int height) { - - pSize = new Dimension(width, height); - pLocation = new Point(x, y); - - if (!SwingWTUtils.isSWTControlAvailable(peer)) - return; - - SwingUtilities.invokeSync(new Runnable() { - public void run() { - setPeerBounds(x, y, width, height); - } - }); - } - - /** Sets the physical bounds of the component */ - public void setBounds(Rectangle r) { - setBounds(r.x, r.y, r.width, r.height); - } - - /** - * Returns the actual bounds of the component (or 0,0,0,0 if it isn't - * realised yet) - */ - public Rectangle getBounds() { - return getPeerBounds(); - } - - public float getAlignmentX() { - return alignmentX; - } - - public float getAlignmentY() { - return alignmentY; - } - - public void setAlignmentX(float val) { - alignmentX = val; - } - - public void setAlignmentY(float val) { - alignmentY = val; - } - /** Sets the focus to the next component as if tab was pressed */ public void transferFocus() { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - peer.traverse(SWT.TRAVERSE_TAB_NEXT); - } - }); + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + peer.traverse(SWT.TRAVERSE_TAB_NEXT); + } + }); } /** Sets the focus to the next component as if shift+tab was pressed */ public void transferFocusBackward() { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - peer.traverse(SWT.TRAVERSE_TAB_PREVIOUS); - } - }); + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + peer.traverse(SWT.TRAVERSE_TAB_PREVIOUS); + } + }); } /** NOT IMPLEMENTED: FIXME - focusCycleRoot not done */ public void transferFocusUpCycle() { } - /** - * Override in container classes to relayout child components - calls - * repaint here - */ - public void invalidateImpl() { - repaint(); - } - - public void invalidate() { - cachedComputedPreferredSize = null; - SwingWTUtils.invalidate(this); - } - /** NOT IMPLEMENTED */ public void validate() { } @@ -945,34 +1275,8 @@ actionCommand = command; } - /** Sets the component's location in it's container */ - public void setLocation(final Point p) { - pLocation = p; - if (!SwingWTUtils.isSWTControlAvailable(peer)) - return; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - setPeerBounds(p.x, p.y, getWidth(), getHeight()); - } - }); - } - /** Sets the component's location in it's container */ - public void setLocation(int x, int y) { - setLocation(new Point(x, y)); - } - - /** Returns the component's X position in it's parent container */ - public int getX() { - return getLocation().x; - } - - /** Returns the component's Y position in it's parent container */ - public int getY() { - return getLocation().y; - } - /** Returns the component's parent */ public Container getParent() { return parent; @@ -991,22 +1295,21 @@ /** Sets the components cursor */ public void setCursor(final swingwt.awt.Cursor c) { pCursor = c; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - try { - if (SwingWTUtils.isSWTControlAvailable(peer)) { - if (c != null) { + + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + try { + if (c != null) peer.setCursor(c.getSWTCursor()); - } else { + else peer.setCursor(null); - } + + } catch (Exception e) { + e.printStackTrace(); } - } catch (IllegalArgumentException e) { - } catch (Exception e) { - e.printStackTrace(); } - } - }); + }); } /** Returns true if the component can receive the focus */ @@ -1052,13 +1355,12 @@ */ public void componentOnlyDispose() { - if (SwingWTUtils.isSWTControlAvailable(peer)) { + if (hasPeer()) SwingUtilities.invokeSync(new Runnable() { public void run() { peer.dispose(); } }); - } peer = null; ppeer = null; @@ -1232,6 +1534,7 @@ * Sends mouse events to component listeners */ public void processMouseEvent(MouseEvent e) { + computeTarget(e); for (int i = 0; i < mouseListeners.size(); i++) { MouseListener ml = (MouseListener) mouseListeners.get(i); if (e.eventID == MouseEvent.MOUSE_CLICKED) @@ -1246,11 +1549,12 @@ ml.mouseReleased(e); } } - + /** * Sends mouse motion events to component listeners */ public void processMouseMotionEvent(MouseEvent e) { + computeTarget(e); for (int i = 0; i < mouseMotionListeners.size(); i++) { MouseMotionListener ml = (MouseMotionListener) mouseMotionListeners .get(i); @@ -1263,6 +1567,28 @@ } /** + * Searches the available frames for the component + * which will be targeted by this mouse event. + * + * This is important to generate callbacks for sub-types + * during the search, but we currently do not use the + * target object. + * + * @param e + */ + protected void computeTarget(MouseEvent e) { + int x = e.getX(), y = e.getY(); + Frame[] frames = Frame.getFrames(); + for (int i = 0; i < frames.length; i++) { + Frame frame = frames[i]; + Object target = frame.findComponentAt(x, y); + if (null != target) { + return; + } + } + } + + /** * Sends mouse wheel events to component listeners */ protected void processMouseWheelEvent(MouseWheelEvent e) { @@ -1332,9 +1658,9 @@ // Destroy our temporary gc and image gc.dispose(); img.dispose(); - } else + } else { paintComponent(new SWTGraphics2DRenderer(e.gc)); - + } } /** @@ -1342,9 +1668,10 @@ * set in the meantime, this routine gets called by JSWTComposite to set the * cached properties. */ - public void setCachedProperties() { - if (peer == null) + public void assertCachedProperties() { + if (! hasPeer()) return; + peer.setToolTipText(pToolTipText); updatePeerBackgroundSWT(); if (pForeground != null) @@ -1375,7 +1702,7 @@ */ public void registerEvents() { - if (!SwingWTUtils.isSWTControlAvailable(peer)) + if (! hasPeer()) return; if (swingWTEventAdapter == null) @@ -1727,7 +2054,7 @@ */ protected void registerExtendedModifyEvents() { if (peer instanceof StyledText) { - boolean success = false; + //boolean success = false; try { Method addMethod = peer.getClass().getMethod( "addExtendedModifyListener", @@ -1738,7 +2065,7 @@ removeMethod.invoke(peer, new Object[] { swingWTEventAdapter }); addMethod.invoke(peer, new Object[] { swingWTEventAdapter }); - success = true; + //success = true; } catch (NoSuchMethodException e) { } catch (SecurityException e) { } catch (IllegalAccessException e) { @@ -1808,16 +2135,13 @@ /** Returns true if this component has the focus */ public boolean hasFocus() { - final boolean[] ret = new boolean[1]; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) - ret[0] = peer.isFocusControl(); - else - ret[0] = false; - } - }); - return ret[0]; + if (hasPeer()) + return ((Boolean) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return Boolean.valueOf(peer.isFocusControl()); + } + })).booleanValue(); + return false; } /** @@ -1834,11 +2158,6 @@ return LOCK; } - /** Returns the component's accessible context */ - public AccessibleContext getAccessibleContext() { - return accessibleContext; - } - public boolean isAncestorOf(Component comp) { boolean returnValue = false; Container parent2 = comp.getParent(); @@ -1903,19 +2222,74 @@ } return f; } - public boolean isDisplayable() - { - final boolean[] ret = new boolean[1]; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) - ret[0] = peer.isVisible(); - else - ret[0] = false; - } - }); - return ret[0]; + + + public boolean isDisplayable() { + if (hasPeer()) + return ((Boolean) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return Boolean.valueOf(peer.isVisible()); + } + })).booleanValue(); + return false; } + /** + * A shorthand to check whether peer already carries an SWT control. + * + * @return + */ + public final boolean hasPeer() { + return SwingWTUtils.isSWTControlAvailable(peer); + } + + /** + * By default, return the debug info. + * + * @return + */ + public String toString() { + return debugId(); + } + + // ACCESSIBILITY + + /** + * Returns the component's accessible context. + */ + public AccessibleContext getAccessibleContext() { + if (null == accessibleContext) + accessibleContext = createAccessibleContext(); + return accessibleContext; + } + + /** + * Sub-types should override this method to create the appropriate + * accessible context for the object. + * + * @return a newly created accessible context + */ + protected AccessibleContext createAccessibleContext() { + return null; + } + + /** + * An implementation of AccessibleContext, which should be extended by sub-types. + * + * @author Thiago Tonelli Bartolomei + */ + protected abstract class AccessibleAWTComponent extends AccessibleContext { + } + + // DEBUG SUPPORT + + /** + * Sub-types can override this to provide a better identifier during debug. + * + * @return + */ + public String debugId() { + return componentName; + } } Index: src/swingwt/awt/Insets.java =================================================================== --- src/swingwt/awt/Insets.java (revision 85) +++ src/swingwt/awt/Insets.java (working copy) @@ -11,10 +11,27 @@ package swingwt.awt; - +/** + * + * TODO Comment!! + * + * @author R. Rawson-Tetley + * @author Thiago Tonelli Bartolomei + */ public class Insets implements Cloneable { - public Insets() { } + public int top; + public int left; + public int bottom; + public int right; + + public Insets() { + this.top = 0; + this.left = 0; + this.bottom = 0; + this.right = 0; + } + public Insets(int top, int left, int bottom, int right) { this.top = top; this.left = left; @@ -22,23 +39,40 @@ this.right = right; } - public int top; - public int left; - public int bottom; - public int right; + public Insets(Insets i) { + this.top = i.top; + this.left = i.left; + this.bottom = i.bottom; + this.right = i.right; + } + public final boolean equals(Insets i) { + // TODO - write hashCode() + return null != i && i.top == top && i.left == left && i.bottom == bottom && i.right == right; + } + public String toString() { return getClass().getName()+"[top="+top+",left="+left+",bottom="+bottom+",right="+right+"]"; } - public Object clone() { - try { - return super.clone(); - } catch (Exception e) { - // never gonna happen - } - - return null; + /** + * Returns a new Insets whose values are the sum of the values in this + * object and the insets passed as argument. + * + * @param i + * @return + */ + public final Insets add(Insets i) { + return new Insets(top + i.top, left + i.left, bottom + i.bottom, right + i.right); } + + /** + * Returns a new Insets object with the same values as this one. + * + * @return + */ + public final Object clone() { + return new Insets(top, left, bottom, right); + } } Index: src/swingwt/awt/Image.java =================================================================== --- src/swingwt/awt/Image.java (revision 85) +++ src/swingwt/awt/Image.java (working copy) @@ -31,6 +31,15 @@ protected swingwt.awt.Graphics2D gc = null; protected ImageProducer source; + /** + * A constructor that simply sets the wrappee. + * + * @param image + */ + Image(org.eclipse.swt.graphics.Image image) { + this.image = image; + } + public Image(){ //image = new org.eclipse.swt.graphics.Image(); Index: src/swingwt/awt/Robot.java =================================================================== --- src/swingwt/awt/Robot.java (revision 85) +++ src/swingwt/awt/Robot.java (working copy) @@ -1,56 +1,152 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ package swingwt.awt; -import swingwt.awt.image.*; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; -// TODO: Implement this. -// for now it is here for Swingwt wrapper func. +import swingwt.awt.event.InputEvent; +import swingwt.awt.image.BufferedImage; +import swingwtx.swing.SwingWTUtils; + +/** + * SWT does not provide a direct counterpart to Robot, but + * we can try to simulate it by posting low level events + * in the display's queue. + * + * @author Thiago Tonelli Bartolomei + */ public class Robot { - public Robot() throws AWTException { - } - public Robot(GraphicsDevice screen) throws AWTException - { - } - public synchronized void mouseMove(int x, int y) - { - } - public synchronized void mousePress(int buttons) - { - } - public synchronized void mouseRelease(int buttons) - { - } - public synchronized void mouseWheel(int wheelAmt) - { - } - public synchronized void keyPress(int keycode) - { - } - public synchronized void keyRelease(int keycode) - { - } - public synchronized Color getPixelColor(int x, int y) - { - return null; - } - public synchronized BufferedImage createScreenCapture(Rectangle screenRect) - { - return null; - } - public synchronized boolean isAutoWaitForIdle() { - return false; - } - public synchronized void setAutoWaitForIdle(boolean isOn) { - } - public synchronized int getAutoDelay() { - return 0; - } - public synchronized void setAutoDelay(int ms) { - } - public synchronized void delay(int ms) { - } - public synchronized void waitForIdle() { - } - public synchronized String toString() { - return getClass().getName(); - } + + protected static Runnable NON_EVENT = new Runnable() { + public void run() { + } + }; + + public Robot() throws AWTException { + } + + public Robot(GraphicsDevice screen) throws AWTException { + } + + /** + * Moves the mouse to the screen position x,y. + * + * @param x the x coordinate + * @param y the y coordinate + */ + public synchronized void mouseMove(int x, int y) { + org.eclipse.swt.widgets.Event event = createEvent(SWT.MouseMove); + event.x = x; + event.y = y; + post(event); + } + + public synchronized void mousePress(int buttons) { + int flag = SWT.NONE; + if (buttons == InputEvent.BUTTON1_MASK) + flag = 1; + // TODO - other buttons + org.eclipse.swt.widgets.Event event = createEvent(SWT.MouseDown); + event.button = flag; + post(event); + } + + public synchronized void mouseRelease(int buttons) { + /* + int flag = SWT.NONE; + if (buttons == InputEvent.BUTTON1_MASK) + flag = 1; + // TODO - other buttons + + org.eclipse.swt.widgets.Event event = createEvent(SWT.MouseUp); + event.button = flag; + post(event);*/ + } + + public synchronized void mouseWheel(int wheelAmt) { + } + + public synchronized void keyPress(int keycode) { + /* + org.eclipse.swt.widgets.Event event = createEvent(SWT.KeyDown); + event.keyCode = KeyEvent.translateAWTKey(keycode); + post(event);*/ + } + + public synchronized void keyRelease(int keycode) { + /* + org.eclipse.swt.widgets.Event event = createEvent(SWT.KeyUp); + event.keyCode = KeyEvent.translateAWTKey(keycode); + post(event);*/ + } + + public synchronized Color getPixelColor(int x, int y) { + return null; + } + + public synchronized BufferedImage createScreenCapture(Rectangle screenRect) { + return null; + } + + public synchronized boolean isAutoWaitForIdle() { + return false; + } + + public synchronized void setAutoWaitForIdle(boolean isOn) { + } + + public synchronized int getAutoDelay() { + return 0; + } + + public synchronized void setAutoDelay(int ms) { + } + + public synchronized void delay(int ms) { + } + + public synchronized void waitForIdle() { + } + + public synchronized String toString() { + return getClass().getName(); + } + + /** + * Posts this event to the default display. + * + * For internal use only. + * + * @param event + */ + protected final void post(final org.eclipse.swt.widgets.Event event) { + + final Display d = SwingWTUtils.getDisplay(); + event.display = d; + d.asyncExec(new Runnable() { + public void run() { + d.post(event); + } + }); + } + + /** + * Creates a low level event of this type. + * + * For internal use only. + * + * @param type + * @return + */ + protected final org.eclipse.swt.widgets.Event createEvent(int type) { + org.eclipse.swt.widgets.Event event = new org.eclipse.swt.widgets.Event(); + event.type = type; + return event; + } } Index: src/swingwt/awt/Polygon.java =================================================================== --- src/swingwt/awt/Polygon.java (revision 85) +++ src/swingwt/awt/Polygon.java (working copy) @@ -11,77 +11,276 @@ package swingwt.awt; -import swingwt.awt.geom.*; +import swingwt.awt.geom.AffineTransform; +import swingwt.awt.geom.PathIterator; +import swingwt.awt.geom.Point2D; +import swingwt.awt.geom.Rectangle2D; +/** + * An implementation of a Polygon composed of line segments. + * + * @author Thiago Tonelli Bartolomei + */ public class Polygon implements Shape { - public int npoints; - public int xpoints[]; - public int ypoints[]; - protected Rectangle bounds; - - public Polygon() { - } - public Polygon(int xpoints[], int ypoints[], int npoints) { - } - public void reset() { - npoints = 0; - bounds = null; - } - public void invalidate() { - bounds = null; - } - public void translate(int deltaX, int deltaY) { - // FIXME: Implement - } - public void addPoint(int x, int y) { - // FIXME: Implement - } - public Rectangle getBounds() { - return getBoundingBox(); - } - public Rectangle getBoundingBox() { - return null; - } - public boolean contains(Point p) { - return contains(p.x, p.y); - } - public boolean contains(int x, int y) { - return contains((double) x, (double) y); - } - public boolean inside(int x, int y) { - return contains((double) x, (double) y); - } - public Rectangle2D getBounds2D() { - return getBounds(); - } - public boolean contains(double x, double y) { - // FIXME: Implement - return false; - } - - public boolean contains(Point2D p) { - // FIXME: Implement - return false; - } - public boolean intersects(double x, double y, double w, double h) { - // FIXME: Implement - return false; - } - public boolean intersects(Rectangle2D r) { - return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - public boolean contains(double x, double y, double w, double h) { - // FIXME: Implement - return false; - } - public boolean contains(Rectangle2D r) { - return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - public PathIterator getPathIterator(AffineTransform at) { - return null; - } - public PathIterator getPathIterator(AffineTransform at, double flatness) { - return null; - } + /** + * Used internally to increment the xpoints/ypoints arrays when needed. + */ + protected final int INCREMENT = 10; + + /** + * The number of points in the polygon. + */ + public int npoints = 0; + + /** + * The array of x coordinates. Only the npoints first values are meaningful. + */ + public int xpoints[] = null; + + /** + * The array of y coordinates. Only the npoints first values are meaningful. + */ + public int ypoints[] = null; + + /** + * A rectangle around the polygon. Calculated on demand and kept synchronized. + */ + protected Rectangle bounds = null; + + /** + * Creates an empty polygon. + */ + public Polygon() { + } + + /** + * Creates a polygon with n points, whose coordinates are taken from the xpoints + * and ypoints arrays. + * + * @param xpoints + * @param ypoints + * @param n + */ + public Polygon(int xpoints[], int ypoints[], int n) { + if (n < 0) + throw new NegativeArraySizeException("npoints < 0"); + + this.xpoints = xpoints; + this.ypoints = ypoints; + this.npoints = n; + } + + /** + * Resets the polygon, deleting all its points and freeing + * the points arrays and bounds. + */ + public void reset() { + this.npoints = 0; + this.xpoints = null; + this.ypoints = null; + this.bounds = null; + } + + /** + * Invalidates the bounds rectangle. + */ + public void invalidate() { + bounds = null; + } + + /** + * Translates this polygon, moving it in the plane. + * + * @param deltaX + * @param deltaY + */ + public void translate(int deltaX, int deltaY) { + for (int i = 0; i < npoints; i++) { + xpoints[i] += deltaX; + ypoints[i] += deltaY; + } + if (null != bounds) { + bounds.translate(deltaX, deltaY); + } + } + + /** + * Adds a new point with these coordinates to the polygon. + * + * @param x + * @param y + */ + public void addPoint(int x, int y) { + if (xpoints == null || npoints == xpoints.length) { + // increase array size + int[] newXpoints = new int[npoints + INCREMENT]; + int[] newYpoints = new int[npoints + INCREMENT]; + if (null != xpoints) { + System.arraycopy(xpoints, 0, newXpoints, 0, npoints); + System.arraycopy(ypoints, 0, newYpoints, 0, npoints); + } + xpoints = newXpoints; + ypoints = newYpoints; + } + xpoints[npoints] = x; + ypoints[npoints] = y; + npoints++; + recomputeBounds(); + } + + /** + * Gets a rectangle which contains the whole polygon. + * + * This rectangle object will be kept synchronized if the polygon + * changes (by adding points or translating, for example). + * + * @return + */ + public Rectangle getBounds() { + return getBoundingBox(); + } + + public Rectangle getBoundingBox() { + if (null == bounds) { + int[] b = computeBounds(); + bounds = new Rectangle(b[0], b[1], b[2], b[3]); + } + return bounds; + } + + public boolean contains(Point p) { + return contains(p.x, p.y); + } + + public boolean contains(int x, int y) { + return contains((double) x, (double) y); + } + + public boolean inside(int x, int y) { + return contains((double) x, (double) y); + } + + public Rectangle2D getBounds2D() { + return getBounds(); + } + + /** + * Check if a point with these coordinates is inside this polygon. + * + * We use Randolph Franklin's point inclusion algorithm. + * + * @param x + * @param y + * @return + */ + public boolean contains(double x, double y) { + // Quick test for the bounding box + if (! getBoundingBox().contains(x, y)) { + return false; + } + + // Use the point inclusion algorithm by Randolph Franklin. + // See http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html + /* + * Copyright (c) 1970-2003, Wm. Randolph Franklin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimers. + * Redistributions in binary form must reproduce the above copyright + * notice in the documentation and/or other materials provided with the + * distribution. The name of W. Randolph Franklin may not be used to + * endorse or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + // This version is a modification of the C version. I am not sure that it works + // properly in all cases (it is very sensitive to the inequalities and types), + // but it was good enough for my tests. + boolean ret = false; + + for (int i = 0, j = npoints - 1; i < npoints; j = i++) + if ((ypoints[i] > y) != (ypoints[j] > y) && + (x < ((xpoints[j] - xpoints[i]) * (y - ypoints[i])) / (ypoints[j] - ypoints[i]) + xpoints[i])) + ret = ! ret; + + return ret; + } + + public boolean contains(Point2D p) { + return contains(p.getX(), p.getY()); + } + + public boolean intersects(double x, double y, double w, double h) { + // FIXME: Implement + return false; + } + + public boolean intersects(Rectangle2D r) { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + public boolean contains(double x, double y, double w, double h) { + // FIXME: Implement + return false; + } + + public boolean contains(Rectangle2D r) { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + public PathIterator getPathIterator(AffineTransform at) { + return null; + } + + public PathIterator getPathIterator(AffineTransform at, double flatness) { + return null; + } + + /** + * Reshapes the bounds rectangle if needed. + */ + protected void recomputeBounds() { + if (null != bounds) { + int[] b = computeBounds(); + bounds.reshape(b[0], b[1], b[2], b[3]); + } + } + + /** + * Computes a bounding box around this polygon. + * + * @return + */ + protected int[] computeBounds() { + int minx = Integer.MAX_VALUE, miny = Integer.MAX_VALUE; + int maxx = Integer.MIN_VALUE, maxy = Integer.MIN_VALUE; + + for (int i = 0; i < npoints; i++) { + if (xpoints[i] > maxx) maxx = xpoints[i]; + if (ypoints[i] > maxy) maxy = ypoints[i]; + if (xpoints[i] < minx) minx = xpoints[i]; + if (ypoints[i] < miny) miny = ypoints[i]; + } + + return new int[] {minx, miny, maxx - minx, maxy - miny}; + } } + Index: src/swingwt/awt/event/KeyEvent.java =================================================================== --- src/swingwt/awt/event/KeyEvent.java (revision 85) +++ src/swingwt/awt/event/KeyEvent.java (working copy) @@ -301,6 +301,10 @@ public static final int VK_UNDEFINED = 0; public static final char CHAR_UNDEFINED = '\uffff'; + // Since 1.5 + public static final int VK_CONTEXT_MENU = 0x020D; + + /** Map of SWT key constants to AWT constants. This is to * ensure binary compatibility for existing Swing/AWT apps. */ Index: src/swingwt/awt/Rectangle.java =================================================================== --- src/swingwt/awt/Rectangle.java (revision 85) +++ src/swingwt/awt/Rectangle.java (working copy) @@ -16,199 +16,254 @@ public class Rectangle extends Rectangle2D implements Shape { - public int x; - public int y; - public int width; - public int height; + public int x; - public Rectangle() { - this(0, 0, 0, 0); - } - public Rectangle(Rectangle r) { - this(r.x, r.y, r.width, r.height); - } - public Rectangle(int x, int y, int width, int height) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } - public Rectangle(int width, int height) { - this(0, 0, width, height); - } - public Rectangle(Point p, Dimension d) { - this(p.x, p.y, d.width, d.height); - } - public Rectangle(Point p) { - this(p.x, p.y, 0, 0); - } - public Rectangle(Dimension d) { - this(0, 0, d.width, d.height); - } - public double getX() { - return x; - } - public double getY() { - return y; - } - public double getWidth() { - return width; - } - public double getHeight() { - return height; - } - public Rectangle getBounds() { - return new Rectangle(x, y, width, height); - } - public Rectangle2D getBounds2D() { - return new Rectangle(x, y, width, height); - } - public void setBounds(Rectangle r) { - setBounds(r.x, r.y, r.width, r.height); - } - public void setBounds(int x, int y, int width, int height) { - reshape(x, y, width, height); - } - public void setRect(double x, double y, double width, double height) { - int x0 = (int) Math.floor(x); - int y0 = (int) Math.floor(y); - int x1 = (int) Math.ceil(x+width); - int y1 = (int) Math.ceil(y+height); - setBounds(x0, y0, x1-x0, y1-y0); - } - public void reshape(int x, int y, int width, int height) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } - public Point getLocation() { - return new Point(x, y); - } - public void setLocation(Point p) { - setLocation(p.x, p.y); - } - public void setLocation(int x, int y) { - move(x, y); - } - public void move(int x, int y) { - this.x = x; - this.y = y; - } - public void translate(int x, int y) { - this.x += x; - this.y += y; - } - public Dimension getSize() { - return new Dimension(width, height); - } - public void setSize(Dimension d) { - setSize(d.width, d.height); - } - public void setSize(int width, int height) { - resize(width, height); - } - public void resize(int width, int height) { - this.width = width; - this.height = height; - } - public boolean contains(Point p) { - return contains(p.x, p.y); - } - public boolean contains(int x, int y) { - return inside(x, y); - } - public boolean contains(Rectangle r) { - return contains(r.x, r.y, r.width, r.height); - } - public boolean contains(int X, int Y, int W, int H) { - return super.contains(X, Y, W, H); - } - public boolean inside(int X, int Y) { - return (width > 0 && height > 0) && - (X >= x && X < x + width) && - (Y >= y && Y < y + height); - } + public int y; - public boolean intersects(Rectangle r) { - return super.intersects(r.x, r.y, r.width, r.height); - } + public int width; - public Rectangle intersection(Rectangle r) { - Rectangle retval = new Rectangle(); - intersect(this, r, retval); - return retval; - } - public boolean isEmpty() { - return (width <= 0) || (height <= 0); - } - - public boolean equals(Object obj) { - if (obj instanceof Rectangle) { - Rectangle r = (Rectangle)obj; - return ((x == r.x) && - (y == r.y) && - (width == r.width) && - (height == r.height)); + public int height; + + /** + * Creates a new rectangle that represents a widget at this location and with this size. + * + * @param location + * @param size + */ + Rectangle(org.eclipse.swt.graphics.Point location, org.eclipse.swt.graphics.Point size) { + x = location.x; + y = location.y; + width = size.x; + height = size.y; } - return super.equals(obj); - } - public String toString() { - return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]"; - } - - public boolean contains(Rectangle2D r) { - return contains((Rectangle) r); - } - - public boolean contains(Point2D p) { - return contains((Point) p); - } - - public boolean contains(double x, double y) { - return contains((int) x, (int) y); - } - - public boolean contains(double x, double y, double w, double h) { - return contains((int) x, (int) y, (int) w, (int) h); - } - - public boolean intersects(Rectangle2D r) { - return intersects((Rectangle) r); - } - - public boolean intersects(double x, double y, double w, double h) { - return intersects((int) x, (int) y, (int) w, (int) h); - } + + public Rectangle() { + this(0, 0, 0, 0); + } - public void grow(int h, int v) { - x -= h; - y -= v; - width += 2*h; - height += 2*v; - } - - public Rectangle2D createIntersection(Rectangle2D r) { - Rectangle2D retval = (Rectangle2D) clone(); - intersect(this, r, retval); - return retval; - } - - public Rectangle union(Rectangle r) { - Rectangle retval = (Rectangle) clone(); - union(this, r, retval); - return retval; - } - - public Rectangle2D createUnion(Rectangle2D r) { - Rectangle2D retval = (Rectangle2D) clone(); - union(this, r, retval); - return retval; - } - - public int outcode(double x, double y) { - // FIXME: Implement - return 0; - } - + public Rectangle(Rectangle r) { + this(r.x, r.y, r.width, r.height); + } + + public Rectangle(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public Rectangle(int width, int height) { + this(0, 0, width, height); + } + + public Rectangle(Point p, Dimension d) { + this(p.x, p.y, d.width, d.height); + } + + public Rectangle(Point p) { + this(p.x, p.y, 0, 0); + } + + public Rectangle(Dimension d) { + this(0, 0, d.width, d.height); + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getWidth() { + return width; + } + + public double getHeight() { + return height; + } + + public Rectangle getBounds() { + return new Rectangle(x, y, width, height); + } + + public Rectangle2D getBounds2D() { + return new Rectangle(x, y, width, height); + } + + public void setBounds(Rectangle r) { + setBounds(r.x, r.y, r.width, r.height); + } + + public void setBounds(int x, int y, int width, int height) { + reshape(x, y, width, height); + } + + public void setRect(double x, double y, double width, double height) { + int x0 = (int) Math.floor(x); + int y0 = (int) Math.floor(y); + int x1 = (int) Math.ceil(x + width); + int y1 = (int) Math.ceil(y + height); + setBounds(x0, y0, x1 - x0, y1 - y0); + } + + public void reshape(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public Point getLocation() { + return new Point(x, y); + } + + public void setLocation(Point p) { + setLocation(p.x, p.y); + } + + public void setLocation(int x, int y) { + move(x, y); + } + + public void move(int x, int y) { + this.x = x; + this.y = y; + } + + public void translate(int x, int y) { + this.x += x; + this.y += y; + } + + public Dimension getSize() { + return new Dimension(width, height); + } + + public void setSize(Dimension d) { + setSize(d.width, d.height); + } + + public void setSize(int width, int height) { + resize(width, height); + } + + public void resize(int width, int height) { + this.width = width; + this.height = height; + } + + public boolean contains(Point p) { + return contains(p.x, p.y); + } + + public boolean contains(int x, int y) { + return inside(x, y); + } + + public boolean contains(Rectangle r) { + return contains(r.x, r.y, r.width, r.height); + } + + public boolean contains(int X, int Y, int W, int H) { + return super.contains(X, Y, W, H); + } + + public boolean inside(int X, int Y) { + return (width > 0 && height > 0) && (X >= x && X < x + width) + && (Y >= y && Y < y + height); + } + + public boolean intersects(Rectangle r) { + return super.intersects(r.x, r.y, r.width, r.height); + } + + public Rectangle intersection(Rectangle r) { + Rectangle retval = new Rectangle(); + intersect(this, r, retval); + return retval; + } + + public boolean isEmpty() { + return (width <= 0) || (height <= 0); + } + + public boolean equals(Object obj) { + if (obj instanceof Rectangle) { + Rectangle r = (Rectangle) obj; + return ((x == r.x) && (y == r.y) && (width == r.width) && (height == r.height)); + } + return super.equals(obj); + } + + public String toString() { + return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + + ",height=" + height + "]"; + } + + public boolean contains(Rectangle2D r) { + return contains((Rectangle) r); + } + + public boolean contains(Point2D p) { + return contains((Point) p); + } + + public boolean contains(double x, double y) { + return contains((int) x, (int) y); + } + + public boolean contains(double x, double y, double w, double h) { + return contains((int) x, (int) y, (int) w, (int) h); + } + + public boolean intersects(Rectangle2D r) { + return intersects((Rectangle) r); + } + + public boolean intersects(double x, double y, double w, double h) { + return intersects((int) x, (int) y, (int) w, (int) h); + } + + public void grow(int h, int v) { + x -= h; + y -= v; + width += 2 * h; + height += 2 * v; + } + + public Rectangle2D createIntersection(Rectangle2D r) { + Rectangle2D retval = (Rectangle2D) clone(); + intersect(this, r, retval); + return retval; + } + + public Rectangle union(Rectangle r) { + Rectangle retval = (Rectangle) clone(); + union(this, r, retval); + return retval; + } + + public Rectangle2D createUnion(Rectangle2D r) { + Rectangle2D retval = (Rectangle2D) clone(); + union(this, r, retval); + return retval; + } + + public int outcode(double x, double y) { + // FIXME: Implement + return 0; + } + + // DEBUG SUPPORT + + /** + * Sub-types can override this to provide a better identifier during debug. + * + * @return + */ + public String debugId() { + return "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]"; + } } Index: src/swingwt/awt/Dimension.java =================================================================== --- src/swingwt/awt/Dimension.java (revision 85) +++ src/swingwt/awt/Dimension.java (working copy) @@ -14,50 +14,90 @@ package swingwt.awt; -import swingwt.awt.geom.*; +import swingwt.awt.geom.Dimension2D; public class Dimension extends Dimension2D { - - public int width; - public int height; - public Dimension() { - this(0, 0); - } - public Dimension(Dimension d) { - this(d.width, d.height); - } - public Dimension(int width, int height) { - this.width = width; - this.height = height; - } - public double getWidth() { - return width; - } - public double getHeight() { - return height; - } - public void setSize(double width, double height) { - this.width = (int) Math.ceil(width); - this.height = (int) Math.ceil(height); - } - public Dimension getSize() { - return new Dimension(width, height); - } - public void setSize(Dimension d) { - setSize(d.width, d.height); - } - public void setSize(int width, int height) { - this.width = width; - this.height = height; - } - public boolean equals(Object obj) { - if (obj instanceof Dimension) { - Dimension d = (Dimension)obj; - return (width == d.width) && (height == d.height); + + public int width; + + public int height; + + /** + * Creates a dimension from the corresponding SWT Point object. + * + * @param point + */ + Dimension(org.eclipse.swt.graphics.Point point) { + width = point.x; + height = point.y; } - return false; - } - public String toString() { - return getClass().getName() + "[width=" + width + ",height=" + height + "]"; - } + + /** + * Creates a (0, 0) Dimension. + */ + public Dimension() { + this(0, 0); + } + + public Dimension(Dimension d) { + this(d.width, d.height); + } + + public Dimension(int width, int height) { + this.width = width; + this.height = height; + } + + public double getWidth() { + return width; + } + + public double getHeight() { + return height; + } + + public void setSize(double width, double height) { + this.width = (int) Math.ceil(width); + this.height = (int) Math.ceil(height); + } + + public Dimension getSize() { + return new Dimension(width, height); + } + + public void setSize(Dimension d) { + setSize(d.width, d.height); + } + + public void setSize(int width, int height) { + this.width = width; + this.height = height; + } + + public boolean equals(Object obj) { + if (obj instanceof Dimension) { + Dimension d = (Dimension) obj; + return (width == d.width) && (height == d.height); + } + return false; + } + + public Object clone() { + return new Dimension(width, height); + } + + public String toString() { + return getClass().getName() + "[width=" + width + ",height=" + height + "]"; + } + + // DEBUG SUPPORT + + /** + * Sub-types can override this to provide a better identifier during debug. + * + * @return + */ + public String debugId() { + return "[width=" + width + ",height=" + height + "]"; + } } Index: src/swingwt/awt/Graphics2D.java =================================================================== --- src/swingwt/awt/Graphics2D.java (revision 85) +++ src/swingwt/awt/Graphics2D.java (working copy) @@ -12,10 +12,13 @@ package swingwt.awt; -import swingwt.awt.geom.*; -import swingwt.awt.font.*; +import java.util.Map; -import java.util.*; +import swingwt.awt.font.FontRenderContext; +import swingwt.awt.font.GlyphVector; +import swingwt.awt.geom.AffineTransform; +import swingwt.awt.image.BufferedImage; +import swingwt.awt.image.BufferedImageOp; public abstract class Graphics2D extends Graphics { @@ -52,4 +55,8 @@ public abstract void clip(Shape s); public abstract FontRenderContext getFontRenderContext(); + public abstract void drawImage(BufferedImage img, + BufferedImageOp op, + int x, + int y); } Index: src/swingwt/awt/Point.java =================================================================== --- src/swingwt/awt/Point.java (revision 85) +++ src/swingwt/awt/Point.java (working copy) @@ -10,55 +10,116 @@ */ package swingwt.awt; -public class Point extends swingwt.awt.geom.Point2D { +import swingwt.awt.geom.Point2D; - public int x; - public int y; - public Point() { - this(0, 0); - } - public Point(Point p) { - this(p.x, p.y); - } - public Point(int x, int y) { - this.x = x; - this.y = y; - } - public double getX() { - return x; - } - public double getY() { - return y; - } - public Point getLocation() { - return new Point(x, y); - } - public void setLocation(Point p) { - setLocation(p.x, p.y); - } - public void setLocation(int x, int y) { - move(x, y); - } - public void setLocation(double x, double y) { - this.x = (int) Math.floor(x+0.5); - this.y = (int) Math.floor(y+0.5); - } - public void move(int x, int y) { - this.x = x; - this.y = y; - } - public void translate(int dx, int dy) { - this.x += dx; - this.y += dy; - } - public boolean equals(Object obj) { - if (obj instanceof Point) { - Point pt = (Point)obj; - return (x == pt.x) && (y == pt.y); +/** + * A point in the plane. + * + * @author R. Rawson-Tetley + * @author Thiago Tonelli Bartolomei + */ +public final class Point extends Point2D { + + /** + * The X axis coordinate. + */ + public int x; + + /** + * The Y axis coordinate. + */ + public int y; + + /** + * Creates a new point based on an SWT point. + * + * @param point + */ + Point(org.eclipse.swt.graphics.Point point) { + x = point.x; + y = point.y; } - return super.equals(obj); - } - public String toString() { - return getClass().getName() + "[x=" + x + ",y=" + y + "]"; - } + + /** + * Creates a point in the origin (0,0). + */ + public Point() { + this(0, 0); + } + + /** + * Clones a point, creating a new one with the same values. + * + * @param p + */ + public Point(Point p) { + this(p.x, p.y); + } + + /** + * Creates a new point with these coordinates. + * + * @param x + * @param y + */ + public Point(int x, int y) { + this.x = x; + this.y = y; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public Point getLocation() { + return new Point(x, y); + } + + public void setLocation(Point p) { + setLocation(p.x, p.y); + } + + public void setLocation(int x, int y) { + move(x, y); + } + + public void setLocation(double x, double y) { + this.x = (int) Math.floor(x + 0.5); + this.y = (int) Math.floor(y + 0.5); + } + + public void move(int x, int y) { + this.x = x; + this.y = y; + } + + public void translate(int dx, int dy) { + this.x += dx; + this.y += dy; + } + + public boolean equals(Object obj) { + if (obj instanceof Point) { + Point pt = (Point) obj; + return (x == pt.x) && (y == pt.y); + } + return super.equals(obj); + } + + /** + * Creates a new point with the same position as this one. + * + * @return + */ + public Object clone() { + return new Point(x, y); + } + + public String toString() { + return getClass().getName() + "[x=" + x + ",y=" + y + "]"; + } } Index: src/swingwt/awt/Frame.java =================================================================== --- src/swingwt/awt/Frame.java (revision 85) +++ src/swingwt/awt/Frame.java (working copy) @@ -12,9 +12,13 @@ package swingwt.awt; +import java.util.ArrayList; + import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Shell; import swingwtx.swing.SwingUtilities; +import swingwtx.swing.SwingUtilities.SwingWTRunnable; import swingwtx.swing.SwingWTUtils; /** @@ -33,8 +37,6 @@ protected int state = NORMAL; protected boolean isMax = false; - private int intRetval; - public Frame() { this(""); } @@ -55,50 +57,79 @@ public boolean isResizable() { return isResizable; } public void remove(MenuComponent menuComponent) { pMenuBar.remove(menuComponent); } + + public void setExtendedState(final int state) { this.state = state; - if (SwingWTUtils.isSWTControlAvailable(peer)) { + + if (hasPeer()) SwingUtilities.invokeSync(new Runnable() { public void run() { if ( ((state & MAXIMIZED_BOTH) > 0) || ((state & MAXIMIZED_HORIZ) > 0) || ((state & MAXIMIZED_VERT) > 0) ) { - peer.setMaximized(true); + ((Shell) peer).setMaximized(true); isMax = true; } else { - peer.setMaximized(false); + ((Shell) peer).setMaximized(false); isMax = false; } if ((state & ICONIFIED) > 0) { - peer.setMinimized(true); + ((Shell) peer).setMinimized(true); isIcon = true; } else { - peer.setMinimized(false); + ((Shell) peer).setMinimized(false); isIcon = false; } } }); - } } + public int getExtendedState() { - if (SwingWTUtils.isSWTControlAvailable(peer)) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (peer.getMaximized()) - intRetval = MAXIMIZED_BOTH; - else if (peer.getMinimized()) - intRetval = ICONIFIED; - else - intRetval = NORMAL; + if (hasPeer()) + return ((Integer) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + if (((Shell) peer).getMaximized()) + return Integer.valueOf(MAXIMIZED_BOTH); + + if (((Shell) peer).getMinimized()) + return Integer.valueOf(ICONIFIED); + + return Integer.valueOf(NORMAL); } - }); - } - else intRetval = state; - return intRetval; + })).intValue(); + + return state; } + public void setUndecorated(boolean undecorated){} + /** + * Returns all frames known to be created (even if they are not opened). + * + * @return + */ + public static Frame[] getFrames() { + final java.util.List framesList = new ArrayList(); + + SwingUtilities.invokeSync(new Runnable() { + public void run() { + Shell[] shells = SwingWTUtils.getDisplay().getShells(); + + // Wrap the shels into frames + + for (int i = 0; i < shells.length; i++) { + Object o = SwingWTUtils.wrap(shells[i]); + if (o instanceof Frame) + framesList.add(o); + } + } + }); + + // Compute the frames array + return (Frame[]) framesList.toArray(new Frame[0]); + } } Index: src/demo/swingset/ButtonDemo.java =================================================================== --- src/demo/swingset/ButtonDemo.java (revision 85) +++ src/demo/swingset/ButtonDemo.java (working copy) @@ -529,7 +529,7 @@ } public void stateChanged(ChangeEvent e) { - /*SingleSelectionModel model = (SingleSelectionModel) e.getSource(); + SingleSelectionModel model = (SingleSelectionModel) e.getSource(); if(model.getSelectedIndex() == 0) { currentControls = buttons; } else if(model.getSelectedIndex() == 1) { @@ -538,7 +538,7 @@ currentControls = checkboxes; } else { currentControls = togglebuttons; - }*/ + } } public Vector getCurrentControls() { Index: src/swingwtx/accessibility/AccessibleExtendedComponent.java =================================================================== --- src/swingwtx/accessibility/AccessibleExtendedComponent.java (revision 0) +++ src/swingwtx/accessibility/AccessibleExtendedComponent.java (revision 0) @@ -0,0 +1,17 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.accessibility; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public interface AccessibleExtendedComponent extends AccessibleComponent { + +} Index: src/swingwtx/accessibility/AccessibleRelationSet.java =================================================================== --- src/swingwtx/accessibility/AccessibleRelationSet.java (revision 85) +++ src/swingwtx/accessibility/AccessibleRelationSet.java (working copy) @@ -11,6 +11,7 @@ package swingwtx.accessibility; + /** * TODO: Implement * @author Naab @@ -18,4 +19,8 @@ */ public class AccessibleRelationSet { + + public boolean add(AccessibleRelation relation) { + return false; + } } Index: src/swingwtx/accessibility/AccessibleRelation.java =================================================================== --- src/swingwtx/accessibility/AccessibleRelation.java (revision 0) +++ src/swingwtx/accessibility/AccessibleRelation.java (revision 0) @@ -0,0 +1,51 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.accessibility; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class AccessibleRelation extends AccessibleBundle { + + public static final String LABEL_FOR = new String("labelFor"); + public static final String LABELED_BY = new String("labeledBy"); + public static final String MEMBER_OF = new String("memberOf"); + public static final String CONTROLLER_FOR = new String("controllerFor"); + public static final String CONTROLLED_BY = new String("controlledBy"); + public static final String LABEL_FOR_PROPERTY = "labelForProperty"; + public static final String LABELED_BY_PROPERTY = "labeledByProperty"; + public static final String MEMBER_OF_PROPERTY = "memberOfProperty"; + public static final String CONTROLLER_FOR_PROPERTY = "controllerForProperty"; + public static final String CONTROLLED_BY_PROPERTY = "controlledByProperty"; + + // Bellow here, fields since 1.5 + public static final String FLOWS_TO = "flowsTo"; + public static final String FLOWS_FROM = "flowsFrom"; + public static final String SUBWINDOW_OF = "subwindowOf"; + public static final String PARENT_WINDOW_OF = "parentWindowOf"; + public static final String EMBEDS = "embeds"; + public static final String EMBEDDED_BY = "embeddedBy"; + public static final String CHILD_NODE_OF = "childNodeOf"; + public static final String FLOWS_TO_PROPERTY = "flowsToProperty"; + public static final String FLOWS_FROM_PROPERTY = "flowsFromProperty"; + public static final String SUBWINDOW_OF_PROPERTY = "subwindowOfProperty"; + public static final String PARENT_WINDOW_OF_PROPERTY = "parentWindowOfProperty"; + public static final String EMBEDS_PROPERTY = "embedsProperty"; + public static final String EMBEDDED_BY_PROPERTY = "embeddedByProperty"; + public static final String CHILD_NODE_OF_PROPERTY = "childNodeOfProperty"; + + public AccessibleRelation(String key, Object target) { + + } + + public AccessibleRelation(String key, Object[] target) { + + } +} Index: src/swingwtx/swing/JTabbedPane.java =================================================================== --- src/swingwtx/swing/JTabbedPane.java (revision 85) +++ src/swingwtx/swing/JTabbedPane.java (working copy) @@ -12,17 +12,24 @@ package swingwtx.swing; -import org.eclipse.swt.widgets.*; -import org.eclipse.swt.*; +import java.util.Iterator; +import java.util.Vector; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; + import swingwt.awt.Component; +import swingwt.awt.Container; import swingwt.awt.Dimension; -import swingwtx.swing.event.*; -import swingwtx.swing.plaf.*; +import swingwtx.swing.SwingUtilities.SwingWTRunnable; +import swingwtx.swing.event.ChangeEvent; +import swingwtx.swing.event.ChangeListener; +import swingwtx.swing.plaf.TabbedPaneUI; -import java.util.*; - public class JTabbedPane extends JComponent implements SwingConstants { protected TabFolder ppeer = null; @@ -32,16 +39,16 @@ /** Tab item cache until added to parent */ protected Vector tabs = new Vector(); - /** Thread safe accessor */ - private int iRetVal = 0; - private String sRetVal = ""; - private Object retval; - - /** The default selection model */ - protected SingleSelectionModel model; + /** The selection model */ + protected SingleSelectionModel model = null; - public JTabbedPane() { } + /** + * Creates an empty tabbed pane with a default single selection model and TOP placement. + */ + public JTabbedPane() { + this(TOP); + } /** * Creates an empty TabbedPane with the specified tab placement @@ -51,9 +58,9 @@ * @param tabPlacement the placement for the tabs relative to the content */ - public JTabbedPane(int tabPlacement) - { + public JTabbedPane(int tabPlacement) { setTabPlacement(tabPlacement); + setModel(new DefaultSingleSelectionModel()); } public void addChangeListener(ChangeListener l) { @@ -115,7 +122,7 @@ private void insertTab(final String title, final Icon icon, final Component component, final String tip, int index, final boolean enabled, boolean fromcache) { // Create the cache entry - if (!fromcache) { + if (! fromcache) { TabItemCache t = new TabItemCache(); t.title = title; t.icon = icon; @@ -123,57 +130,61 @@ t.tip = tip; t.enabled = enabled; tabs.insertElementAt(t,index); - t = null; - return; + comps.add(component); + + } else { + + final JTabbedPane me = this; + SwingUtilities.invokeSync(new Runnable() { + public void run() { + if (!SwingWTUtils.isSWTControlAvailable(ppeer)) return; + + TabItem t = new TabItem(ppeer, SWT.NONE); + + // Make sure the component contained by this + // TabItem gets created now. + try { + component.setSwingWTParent(me); + } + catch (Exception e) { + e.printStackTrace(); + } + + if (title != null) t.setText(SwingWTUtils.removeHTML(title)); + if (icon != null) t.setImage(SwingWTUtils.getSWTImageFromSwingIcon(me, icon)); + + // Only display the component if it's enabled + if (component != null && enabled) t.setControl(component.getSWTPeer()); + + if (tip != null) t.setToolTipText(tip); + t.setData("enabled", (enabled ? "true" : "false")); + + // Display the thing + postponeLayout(); + } + }); } - final JTabbedPane me = this; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (!SwingWTUtils.isSWTControlAvailable(ppeer)) return; + // Swing always selects the first tab when a new tab is added + if (this.getTabCount() > 0 && this.getSelectedIndex() != 0) + this.setSelectedIndex(0); + } - TabItem t = new TabItem(ppeer, SWT.NONE); + public Icon getIconAt(final int index) { + if (!SwingWTUtils.isSWTControlAvailable(ppeer)) { + TabItemCache t = (TabItemCache) tabs.get(index); + return t.icon; + } - // Make sure the component contained by this - // TabItem gets created now. - try { - component.setSwingWTParent(me); - } - catch (Exception e) { - e.printStackTrace(); - } - - if (title != null) t.setText(SwingWTUtils.removeHTML(title)); - if (icon != null) t.setImage(SwingWTUtils.getSWTImageFromSwingIcon(me, icon)); - - // Only display the component if it's enabled - if (component != null && enabled) t.setControl(component.getSWTPeer()); - - if (tip != null) t.setToolTipText(tip); - t.setData("enabled", (enabled ? "true" : "false")); - - // Display the thing - postponeLayout(); - } - }); - } - - public Icon getIconAt(final int index) { - if (!SwingWTUtils.isSWTControlAvailable(ppeer)) { - TabItemCache t = (TabItemCache) tabs.get(index); - return t.icon; - } - else { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - swingwt.awt.Image image = new swingwt.awt.Image(); - image.image = ppeer.getItem(index).getImage(); - retval = new ImageIcon(image); - } - }); - return (Icon) retval; - } - } + return (Icon) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + swingwt.awt.Image image = new swingwt.awt.Image(); + image.image = ppeer.getItem(index).getImage(); + return new ImageIcon(image); + } + }); + } + public void setIconAt(final int index, final Icon icon) { final JTabbedPane pthis = this; if (!SwingWTUtils.isSWTControlAvailable(ppeer)) { @@ -188,21 +199,19 @@ } }); } - - public boolean isEnabledAt(final int index) { - if (SwingWTUtils.isSWTControlAvailable(ppeer)) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - retval = ppeer.getItem(index).getData("enabled"); - } - }); - return retval.equals("true"); - } - else { - TabItemCache t = (TabItemCache) tabs.get(index); - return t.enabled; - } - } + + public boolean isEnabledAt(final int index) { + if (SwingWTUtils.isSWTControlAvailable(ppeer)) { + + return ((Boolean) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return Boolean.valueOf(ppeer.getItem(index).getData("enabled").equals("true")); + } + })).booleanValue(); + } + return ((TabItemCache) tabs.get(index)).enabled; + } + public void setEnabledAt(final int index, final boolean b) { if (SwingWTUtils.isSWTControlAvailable(ppeer)) { SwingUtilities.invokeSync(new Runnable() { @@ -222,81 +231,83 @@ t.enabled = b; } } + + public int getTabCount() { + if (!SwingWTUtils.isSWTControlAvailable(ppeer)) + return tabs.size(); + + return ((Integer) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return Integer.valueOf(ppeer.getItemCount()); + } + })).intValue(); + } - public int getTabCount() { - if (!SwingWTUtils.isSWTControlAvailable(ppeer)) - return tabs.size(); - else { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - iRetVal = ppeer.getItemCount(); - } - }); - return iRetVal; - } + /** + * Gets the index of the selected tab or -1 if no + * tab is selected. + * + * @return + */ + public int getSelectedIndex() { + return model.getSelectedIndex(); } - public int getSelectedIndex() { - if (SwingWTUtils.isSWTControlAvailable(ppeer)) { + + /** + * Sets the selected tab to be the one with this index. + * + * @param index + */ + public void setSelectedIndex(final int index) { + if (SwingWTUtils.isSWTControlAvailable(ppeer)) SwingUtilities.invokeSync(new Runnable() { public void run() { - iRetVal = ppeer.getSelectionIndex(); + ppeer.setSelection(index); } }); - } - else - iRetVal = -1; - return iRetVal; + selectionChanged(index); } public swingwt.awt.Component getSelectedComponent() { int i = getSelectedIndex(); if (i != -1) + //return (Component) comps.get(i); return ((TabItemCache) tabs.get(i)).component; else return null; } - public void setSelectedIndex(final int index) { - if (SwingWTUtils.isSWTControlAvailable(ppeer)) - SwingUtilities.invokeSync(new Runnable() { - public void run() { - ppeer.setSelection(index); - } - }); - } + public void setSelectedComponent(Component panel) { setSelectedIndex(indexOfComponent(panel)); } public void removeTabAt(final int index) { + if (SwingWTUtils.isSWTControlAvailable(ppeer)) { SwingUtilities.invokeSync(new Runnable() { public void run() { - tabs.removeElementAt(index); ppeer.getItem(index).dispose(); } }); } - else - tabs.removeElementAt(index); + comps.removeElementAt(index); + tabs.removeElementAt(index); } + + public String getTitleAt(final int index) { + + if (!SwingWTUtils.isSWTControlAvailable(ppeer)) + return ((TabItemCache) tabs.get(index)).title; + + return (String) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return ppeer.getItem(index).getText(); + } + }); + } - public String getTitleAt(final int index) { - if (SwingWTUtils.isSWTControlAvailable(ppeer)) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - sRetVal = ppeer.getItem(index).getText(); - } - }); - return sRetVal; - } - else { - TabItemCache t = (TabItemCache) tabs.get(index); - return t.title; - } - } - public void setTitleAt(final int index, final String title) { if (SwingWTUtils.isSWTControlAvailable(ppeer)) { SwingUtilities.invokeSync(new Runnable() { @@ -312,18 +323,15 @@ } public String getToolTipTextAt(final int index) { - if (SwingWTUtils.isSWTControlAvailable(ppeer)) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - sRetVal = ppeer.getItem(index).getToolTipText(); - } - }); - return sRetVal; - } - else { - TabItemCache t = (TabItemCache) tabs.get(index); - return t.tooltip; - } + + if (!SwingWTUtils.isSWTControlAvailable(ppeer)) + return ((TabItemCache) tabs.get(index)).tooltip; + + return (String) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + return ppeer.getItem(index).getToolTipText(); + } + }); } public void setToolTipTextAt(final int index, final String text) { @@ -433,26 +441,15 @@ protected void layoutTab() { Control p = ppeer.getItem(ppeer.getSelectionIndex()).getControl(); - if (p instanceof Composite) + if (p instanceof Composite && null != ((Composite) p).getLayout()) ((Composite) p).layout(true); else - parent.invalidate(); + this.getSelectedComponent().invalidate(); } - /** - * Process change events - fired when the tab changes - */ - protected void processChangeEvent(ChangeEvent e) { - Iterator i = changeListeners.iterator(); - while (i.hasNext()) { - ChangeListener l = (ChangeListener) i.next(); - l.stateChanged(e); - } - } - public void setSwingWTParent(swingwt.awt.Container parent) throws Exception { descendantHasPeer = true; - ppeer = new TabFolder(parent.getComposite(), SwingWTUtils.translateSwingAlignmentConstant(pTabPlacement)); + ppeer = new TabFolder(parent.getComposite(), SWT.NO_RADIO_GROUP | SwingWTUtils.translateSwingAlignmentConstant(pTabPlacement)); peer = ppeer; composite = ppeer; this.parent = parent; @@ -468,23 +465,25 @@ // -- Tab is selected, may want to block it if we have it // flagged as disabled. - final JTabbedPane me = this; ppeer.addSelectionListener(new org.eclipse.swt.events.SelectionListener() { public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) { // We don't send events if the tab is disabled if (checkTabEnabled(e)) { - postponeLayout(); // Update layout of tab if we went to a new one + + // Update layout of tab if we went to a new one + postponeLayout(); - // Send change event - ChangeEvent ce = new ChangeEvent(me); - processChangeEvent(ce); - + // Update model and fire events + selectionChanged(ppeer.getSelectionIndex()); + // With Swing, components on a JTabbedPane receive a repaint // event on focus gain. For compatibility with code that relies on // this, fire off a show() call here: cachedComputedPreferredSize = null; - getSelectedComponent().invalidate(); - getSelectedComponent().show(); + Component selected = getSelectedComponent(); + selected.invalidate(); + selected.show(); + // ((Container) selected).debug_showContainmentTree(); } } public void widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent e) {} @@ -493,7 +492,38 @@ // Make sure first one gets displayed if (ppeer.getItemCount() > 0) postponeLayout(); + } + + /** + * Forces laying out of this container's child components again. + */ + //@Override + /* + public void invalidateImpl() { + Component c = getSelectedComponent(); + Dimension d = c.getPreferredSize(); + c.setBounds(0, 20, d.width, d.height); + }*/ + + /** + * Lets the model know about the new index and fires an event to change + * listeners, if needed. + * + * @param newIndex the newly selected tab index. + */ + protected final void selectionChanged(int newIndex) { + // Update model + model.setSelectedIndex(newIndex); + // Send change event if there are listeners + if (! changeListeners.isEmpty()) { + ChangeEvent ce = new ChangeEvent(model); + Iterator i = changeListeners.iterator(); + while (i.hasNext()) { + ChangeListener l = (ChangeListener) i.next(); + l.stateChanged(ce); + } + } } /** Returns true if the tab is enabled according to the data set on it. @@ -530,13 +560,44 @@ } } + /** + * Use the parent's preferred size if it was set by the + * user; otherwise, use the standard preferred size + * calculation. + * + * @return + */ + //@Override + public Dimension calculatePreferredSize() { + Container parent = getParent(); + if (null != parent && parent.isPreferredSizeSet()) + return parent.getPreferredSize(); + + return super.calculatePreferredSize(); + } + + /** + * Use the parent's preferred size if it was set by the + * user; otherwise, compute from the peer. + * + * @return + */ + //@Override protected Dimension computePreferredSize() { - Component content = getSelectedComponent(); - Dimension size = (content != null ? content.getPreferredSize() : new Dimension()); - org.eclipse.swt.graphics.Point p = peer.computeSize(-1, -1); - size.width = Math.max(size.width, p.x); - size.height += p.y; - return size; + Container parent = getParent(); + if (null != parent && parent.isPreferredSizeSet()) + return parent.getPreferredSize(); + + return (Dimension) SwingUtilities.sync(new SwingWTRunnable() { + public Object exec() { + Component content = getSelectedComponent(); + Dimension size = (content != null ? content.getPreferredSize() : new Dimension()); + org.eclipse.swt.graphics.Point p = peer.computeSize(-1, -1); + size.width = Math.max(size.width, p.x); + size.height += p.y; + return size; + } + }); } public Dimension getMaximumSize() { @@ -567,9 +628,11 @@ this.model = model; repaint(); } + public TabbedPaneUI getUI() { return (TabbedPaneUI)componentUI; } + public void setUI(TabbedPaneUI ui) { componentUI = ui; } Index: src/swingwtx/swing/AbstractButton.java =================================================================== --- src/swingwtx/swing/AbstractButton.java (revision 85) +++ src/swingwtx/swing/AbstractButton.java (working copy) @@ -11,13 +11,25 @@ package swingwtx.swing; -import swingwt.awt.event.*; -import swingwtx.swing.event.*; -import org.eclipse.swt.widgets.*; -import swingwt.awt.Graphics; +import java.util.List; +import java.util.Vector; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseTrackListener; +import org.eclipse.swt.widgets.Button; -import java.util.*; +import swingwt.awt.Dimension; +import swingwt.awt.Insets; +import swingwt.awt.event.ActionEvent; +import swingwt.awt.event.ActionListener; +import swingwt.awt.event.ItemEvent; +import swingwt.awt.event.ItemListener; +import swingwtx.swing.SwingUtilities.SwingWTRunnable; +import swingwtx.swing.event.ChangeEvent; +import swingwtx.swing.event.ChangeListener; /** * Swing Abstract Button superclass for improved @@ -26,53 +38,164 @@ * to provide a better hierarchy and prevent ActionEvents * being fired twice. * + * This class also implements ButtonModel so that by default we do not have to create 2 objects + * to wrap a Button. + * * @author Diane Trout * @author Robin Rawson-Tetley * @author Brian Sant + * @author Thiago Tonelli Bartolomei */ - public abstract class AbstractButton extends JComponent implements SwingConstants { + public abstract class AbstractButton extends JComponent implements SwingConstants, ButtonModel { - protected Button ppeer = null; + /** + * The SWT Button implemnenting this AbstractButton. + */ + protected Button ppeer = null; + + /** + * Contains always the text to be presented by the Buttons, with *no* mnemonic. + * + * Note that the ppeer's text will be a composition of this text plus the mnemonic. + */ protected String pText = null; + + /** + * The mnemonic char for this button. + */ + protected char pMnemonic = ' '; + + /** + * A model to carry some state about this button. + */ protected ButtonModel pModel; + + /** + * The group to which this button belongs. + */ protected ButtonGroup pGroup; - protected char pMnemonic = ' '; + + /** + * Cache for selection. This value should be kept synchronized with + * the ppeer value even after it is created. + */ protected boolean pSelection = false; + + /** + * Cache for rollover + * + * TODO - currently rollover (as well as isRolloverEnabled) has no effect. + * We have to pay attention to what happens with the icons when these methods + * are used. + */ + protected boolean pRollover = false; + + // TODO - these boolean values can be described by a single int with masks + /** + * Value for armed, unavailable in SWT. + */ + protected boolean pArmed = false; + + /** + * Value for pressed, unavailable in SWT. + */ + protected boolean pPressed = false; + + /** + * The last time this button was clicked. + * + * This is needed to avoid triggering events twice. + */ + protected int lastClick = -1; + + /** + * True if pText contains HTML tags. + */ + protected boolean containsHTML = false; + + /** + * The margin around the button, if any. + */ + protected Insets pMargin = null; + + /** + * Contains the icons that can be added to a button. + * + * The array is only instantiated when an icon is added. The different icons + * can be accessed using the following constants as index in this array. + */ + protected Icon[] icons = null; + + // Constants for additionalIcons indexes + public static final int DEFAULT_ICON = 0; + public static final int PRESSED_ICON = 1; + public static final int DISABLED_ICON = 2; + public static final int SELECTED_ICON = 3; + public static final int DISABLED_SELECTED_ICON = 4; + public static final int ROLLOVER_ICON = 5; + public static final int ROLLOVER_SELECTED_ICON = 6; + protected int pHTextPosition = LEFT; protected int pVTextPosition = TOP; protected int pHAlign = LEFT; protected int pVAlign = TOP; - protected Icon pIcon = null; protected Action pAction = null; - protected Vector changeListeners = new Vector(); - protected Vector itemListeners = new Vector(); + protected List/**/ changeListeners = null; + protected List/**/ itemListeners = null; + protected List/**/ actionListeners = null; + /** + * By default this object is its own model. + */ + public AbstractButton() { + pModel = this; + + // will currently set to null, until UIDefaults is properly implemented + setBorder(UIManager.getBorder("Button.border")); + } + + /** + * Sets the action to be executed when this button is clicked. + * + * This method will replace a previous action, if any, and will use + * attributes of the action to use as icon, text, tooltip, and mnemonic. + * + * @param a + */ public void setAction(Action a) { - if (a == null || a.equals(pAction)) return; - - if (pAction != null) { removeActionListener(pAction); } - if (a instanceof ActionListener) { addActionListener(a); } - - if (a.getValue(Action.SMALL_ICON) != null) - setIcon((Icon) a.getValue(Action.SMALL_ICON)); - if (a.getValue(Action.NAME) != null) - setText((String) a.getValue(Action.NAME)); - if (a.getValue(Action.SHORT_DESCRIPTION) != null) - setToolTipText((String) a.getValue(Action.SHORT_DESCRIPTION)); - if (a.getValue(Action.MNEMONIC_KEY) != null) - setMnemonic(((Integer) a.getValue(Action.MNEMONIC_KEY)).intValue()); - - // LONG_DESCRIPTION is not used in the orginal Swing implementation. - // The javadoc mentions that the LONG_DESCRIPTION may be used in - // an application's "context sensitive help", but Swing components - // don't use it directly. - - setEnabled(a.isEnabled()); - pAction = a; - } - + if (a == null || a.equals(pAction)) + return; + + if (pAction != null) + removeActionListener(pAction); + + if (a instanceof ActionListener) + addActionListener(a); + + + if (a.getValue(Action.SMALL_ICON) != null) + setIcon((Icon) a.getValue(Action.SMALL_ICON)); + + if (a.getValue(Action.NAME) != null) + setText((String) a.getValue(Action.NAME)); + + if (a.getValue(Action.SHORT_DESCRIPTION) != null) + setToolTipText((String) a.getValue(Action.SHORT_DESCRIPTION)); + + if (a.getValue(Action.MNEMONIC_KEY) != null) + setMnemonic(((Integer) a.getValue(Action.MNEMONIC_KEY)).intValue()); + + // LONG_DESCRIPTION is not used in the orginal Swing implementation. + // The javadoc mentions that the LONG_DESCRIPTION may be used in + // an application's "context sensitive help", but Swing components + // don't use it directly. + + setEnabled(a.isEnabled()); + pAction = a; + } + /** * Works like setAction. * @param a The action to set @@ -85,87 +208,357 @@ removeActionListener(a); } - public Action getAction() { return pAction; } - - /** If the action command is null, return the button text like Swing */ - public String getActionCommand() { - if (actionCommand == null) - return getText(); - else if (actionCommand.equals("")) - return getText(); - else - return actionCommand; - } - - public void setIcon(Icon icon) {} - public void setPressedIcon(Icon icon) {} - public void setRolloverIcon(Icon icon) {} - public void setRolloverSelectedIcon(Icon icon) {} - public void setRolloverEnabled(boolean b) {} - public boolean isRolloverEnabled() { return true; } - public void setDisabledIcon(Icon icon) {} - public void setSelectedIcon(Icon icon) {} - - public void setBorderPainted(boolean b) {} - public void setFocusPainted(boolean b) {} - public void setContentAreaFilled(boolean b) {} - - public void addChangeListener(ChangeListener l) { - changeListeners.add(l); - } - - public void removeChangeListener(ChangeListener l) { - changeListeners.remove(l); - } - - - public void addItemListener(ItemListener l) { - itemListeners.add(l); + public Action getAction() { + return pAction; } - public void removeItemListener(ItemListener l) { - itemListeners.remove(l); + // ICON HANDLING + + /** + * Actually sets the icon that should be displayed by the peer. + * + * @param icon + */ + protected final void setPeerImage(final Icon icon) { + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + ppeer.setImage(SwingWTUtils.getSWTImageFromSwingIcon(AbstractButton.this, icon)); + } + }); + } + + /** + * Lazy accessor to the additionalIcons array. + * + * @return + */ + protected final Icon[] getIcons() { + if (null == icons) + icons = new Icon[7]; + return icons; + } + + /** + * Checks whether this button has defined a default icon. + * + * @return + */ + protected final boolean hasDefaultIcon() { + return null != icons && null != icons[DEFAULT_ICON]; + } + + /** + * Returns the appropriate icon to display based on the state of the button (like + * isEnabled() and isSelected() and on these two parameters. + * + * Note that this method may return null if there is no icon set for the current + * state. Clients should probably use the default button if that happens. + * + * @param isPressed + * @param isRollOver + * @return + */ + protected final Icon selectIcon(boolean isPressed, boolean isRollOver) { + + if (isPressed) + return getIcons()[PRESSED_ICON]; + + // assuming not pressed + if (this.isEnabled()) { + if (this.isSelected()) { + return isRollOver? getIcons()[ROLLOVER_SELECTED_ICON] : getIcons()[SELECTED_ICON]; + } else { + return isRollOver? getIcons()[ROLLOVER_ICON] : getIcons()[DEFAULT_ICON]; + } + } + + // assuming not enabled + return isSelected() ? getIcons()[DISABLED_SELECTED_ICON] : getIcons()[DISABLED_ICON]; + } + + /** + * Updates the icon with the peer. + * + * The icon to display is selected with selectIcon. If this button does not + * have the appropriate icon, then the default icon is used. + * + * @param isPressed + * @param isRollOver + * @see #selectIcon(boolean, boolean) + */ + protected final void updateIcon(boolean isPressed, boolean isRollOver) { + Icon icon = this.selectIcon(isPressed, isRollOver); + this.setPeerImage(null == icon ? getIcon() : icon); + } + + /** + * Gets the button's default icon. + * + * @return + */ + public Icon getIcon() { + if (null == icons) + return null; + return getIcons()[DEFAULT_ICON]; } + /** + * Sets the default icon to show in the button. + * + * @param icon + */ + public void setIcon(Icon icon) { + getIcons()[DEFAULT_ICON] = icon; + } + + /** + * Sets the icon to show when the button is pressed. + * + * @param icon + */ + public void setPressedIcon(Icon icon) { + getIcons()[PRESSED_ICON] = icon; + } + + /** + * Sets the icon to show when the button is disabled. + * + * @param icon + */ + public void setDisabledIcon(Icon icon) { + getIcons()[DISABLED_ICON] = icon; + } + + /** + * Sets the icon to show when the button is selected, + * but not pressed. + * + * @param icon + */ + public void setSelectedIcon(Icon icon) { + getIcons()[SELECTED_ICON] = icon; + } + + /** + * Sets the icon to show when the button is not selected + * and there is a mouse over it. + * + * @param icon + */ + public void setRolloverIcon(Icon icon) { + getIcons()[ROLLOVER_ICON] = icon; + } + + /** + * Sets the icon to show when the button is selected and there + * is a mouse over it. + * + * @param icon + */ + public void setRolloverSelectedIcon(Icon icon) { + getIcons()[ROLLOVER_SELECTED_ICON] = icon; + } + + /** + * Sets the icon to show when the button is selected and disabled. + * + * @param icon + */ + public void setDisabledSelectedIcon(Icon icon) { + getIcons()[DISABLED_SELECTED_ICON] = icon; + } + + + public void setRolloverEnabled(boolean b) { + } + + public boolean isRolloverEnabled() { + return true; + } + + public void setBorderPainted(boolean b) { + } + + public void setFocusPainted(boolean b) { + } + + public void setContentAreaFilled(boolean b) { + } + + /** Overridden as we use the Button selection for action events */ protected void registerActionEvents() { - // Handle selection as ActionEvent + + // TODO - use this to generate rollover callbacks + ppeer.addMouseTrackListener(new MouseTrackListener() { + + public void mouseHover(MouseEvent e) { + // System.out.println("Mouse hover " + e); + } + + public void mouseExit(MouseEvent e) { + // System.out.println("Mouse exit " + e); + updateIcon(false, false); + } + + public void mouseEnter(MouseEvent e) { + // System.out.println("Mouse enter " + e); + updateIcon(false, true); + } + }); + + // When the button is clicked, we generate down() and up() events + ppeer.addMouseListener(new MouseListener() { + public void mouseDown(MouseEvent e) { + try { + updateIcon(true, false); + down(); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + public void mouseUp(MouseEvent e) { + // record last click before processing event + lastClick = e.time; + try { + up(); + updateIcon(false, false); + } catch (Exception exception) { + exception.printStackTrace(); + } + } + public void mouseDoubleClick(MouseEvent e) {} + }); + + // When the button is clicked with the keyboard, we use a key listener + // for the down() event, and a selection listener for the up() + ppeer.addKeyListener(new KeyListener() { + public void keyReleased(KeyEvent e) { + updateIcon(true, false); + down(); + } + public void keyPressed(KeyEvent e) {} + }); ppeer.addSelectionListener(new org.eclipse.swt.events.SelectionListener() { public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) { - processActionEvent(0); + if (e.time != lastClick) { + // avoid trigger up() when the selection event is part of a mouse click, + // which occur at the same time + up(); + updateIcon(false, false); + } } public void widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent e) {} - }); + }); } - public void setHorizontalAlignment(final int align) { pHAlign = align; SwingUtilities.invokeSync(new Runnable() { public void run() { if (SwingWTUtils.isSWTControlAvailable(ppeer)) ppeer.setAlignment(SwingWTUtils.translateSwingAlignmentConstant(align) | SwingWTUtils.translateSwingAlignmentConstant(pVAlign));}}); } - public void setVerticalAlignment(final int align) { pVAlign = align; SwingUtilities.invokeSync(new Runnable() { public void run() {if (SwingWTUtils.isSWTControlAvailable(ppeer))ppeer.setAlignment(SwingWTUtils.translateSwingAlignmentConstant(align) | SwingWTUtils.translateSwingAlignmentConstant(pHAlign));}});} - public int getHorizontalAlignment() { return pHAlign; } - public int getVerticalAlignment() { return pVAlign; } - public void setHorizontalTextPosition(int textpos) { setHorizontalAlignment(textpos); } - public void setVerticalTextPosition(int textpos) { setVerticalAlignment(textpos); } - public int getHorizontalTextPosition() { return getHorizontalAlignment(); } - public int getVerticalTextPosition() { return getVerticalAlignment(); } - + /** + * Sets the horizontal alignment of icon and text in the button. + * + * SwingWT supports all horizontal constants (LEFT, LEADING, CENTER, TRAILING, RIGHT). + * + * @param align + */ + public void setHorizontalAlignment(final int align) { + // only update if needed + if (align != pHAlign) { + pHAlign = align; + + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + ppeer.setAlignment(SwingWTUtils.translateSwingAlignmentConstant(align)); + // since SWT does not support vertical alignment, do not even try.. + // (vertical "center" was causing problems with horizontal alignment) + //| SwingWTUtils.translateSwingAlignmentConstant(pVAlign)); + } + }); + } + } + + /** + * Gets the horizontal alignment of icon and text with respect to the button. + * + * @return + */ + public int getHorizontalAlignment() { + return pHAlign; + } + + + /** + * Sets the vertical alignment of icon and text. + * + * Swing supports BOTTOM, CENTER and TOP. However, SWT does not support vertical + * alignments. Therefore, this method will only keep the constant to return in + * the getter, but there is no effect to the GUI. + * + * @param align + */ + public void setVerticalAlignment(final int align) { + pVAlign = align; + /* + SwingUtilities.invokeSync(new Runnable() { + public void run() { + if (SwingWTUtils.isSWTControlAvailable(ppeer)) + ppeer.setAlignment(SwingWTUtils.translateSwingAlignmentConstant(align) + | SwingWTUtils.translateSwingAlignmentConstant(pHAlign)); + } + });*/ + } + + /** + * Gets the constant representing vertical alignment. + * + * Note that SwingWT does not support vertical alignments. + * + * @see #setVerticalAlignment(int) + * @return + */ + public int getVerticalAlignment() { + return pVAlign; + } + + public void setHorizontalTextPosition(int textpos) { + setHorizontalAlignment(textpos); + } + + public void setVerticalTextPosition(int textpos) { + setVerticalAlignment(textpos); + } + + public int getHorizontalTextPosition() { + return getHorizontalAlignment(); + } + + public int getVerticalTextPosition() { + return getVerticalAlignment(); + } + /** * Sends action events to listeners. */ public void processActionEvent(int id) { - ActionEvent ae = new ActionEvent(this, id, this.getActionCommand()); - for (int i = 0; i < actionListeners.size(); i++) { - ActionListener al = (ActionListener) actionListeners.get(i); - al.actionPerformed(ae); - } + if (null != actionListeners) { + ActionEvent ae = new ActionEvent(this, id, this.getActionCommand()); + for (int i = 0; i < actionListeners.size(); i++) { + ActionListener al = (ActionListener) actionListeners.get(i); + al.actionPerformed(ae); + } + } // Send the actions as changes - ChangeEvent ce = new ChangeEvent(this); - for (int i = 0; i < changeListeners.size(); i++) { - ChangeListener cl = (ChangeListener) changeListeners.get(i); - cl.stateChanged(ce); - } - + if (null != changeListeners) { + ChangeEvent ce = new ChangeEvent(this); + for (int i = 0; i < changeListeners.size(); i++) { + ChangeListener cl = (ChangeListener) changeListeners.get(i); + cl.stateChanged(ce); + } + } + // Send item events too processItemEvent(); } @@ -174,99 +567,221 @@ * Handles firing of Item events for when selection changes */ public void processItemEvent() { - if (itemListeners.size() == 0) return; - boolean isSelected = pSelection; - if (SwingWTUtils.isSWTControlAvailable(ppeer)) isSelected = ppeer.getSelection(); - ItemEvent e = new ItemEvent(this, 0, this, (isSelected ? ItemEvent.SELECTED : ItemEvent.DESELECTED)); - for (int i = 0; i < itemListeners.size(); i++) { - ItemListener il = (ItemListener) itemListeners.get(i); - il.itemStateChanged(e); + boolean isSelected = this.isSelected(); + + if (null != itemListeners) { + ItemEvent e = new ItemEvent(this, 0, this, (isSelected ? ItemEvent.SELECTED : ItemEvent.DESELECTED)); + + for (int i = 0; i < itemListeners.size(); i++) { + ItemListener il = (ItemListener) itemListeners.get(i); + il.itemStateChanged(e); + } } - // If the item is selected, and it is part of a group, tell the group - if (isSelected && pGroup != null) { - pGroup.setSelected(this.getModel(), true); - } } - public String getLabel() { return getText(); } - public void setLabel(String text) { setText(text); } - public String getText() { return pText; } - public void setText(String text) { - pText = text; - if (pText == null) pText = ""; - showMnemonic(); - if (SwingWTUtils.isSWTControlAvailable(ppeer)) - SwingUtilities.invokeSync(new Runnable() { - public void run() { - ppeer.setText(pText); - } - }); - } - - public int getMnemonic() { return pMnemonic; }; - public void setMnemonic(char mnemonic) { pMnemonic = mnemonic; showMnemonic(); } - public void setMnemonic(int mnemonic) { pMnemonic = (char) mnemonic; showMnemonic(); } + /** + * Creates the default margin for buttons. + * + * This is based on JButton... + * + * @return + */ + protected Insets createDefaultMargin() { + // This is the default margin with the standard L&F in Java 1.6, GTK for Linux. + // It may vary depending on platforms and L&F + return new Insets(5, 17, 5, 17); + } - protected void showMnemonic() { - final Object me = this; + /** + * Sets the margin around this button. + * + * @param i + */ + public void setMargin(Insets i) { + + if (null == i) { + this.pMargin = createDefaultMargin(); + } else { + this.pMargin = i; + } + + this.revalidate(); + } + + /** + * Gets this button's margin, if any. + * + * @return + */ + public Insets getMargin() { + return (null == pMargin) ? + null : + new Insets(pMargin); + } + + /** + * Gets a new dimension object that represents the margin around this button. + * + * The margin is either the user-set margin or the default margin of + * this object. + * + * @return + */ + protected final Dimension getMarginSpace() { + Insets i = pMargin; + if (null == i) + i = createDefaultMargin(); + + return new Dimension(i.left + i.right, i.top + i.bottom); + } + + /** + * Returns getText(); + * + * @return + * @see #getText() + */ + public String getLabel() { + return getText(); + } + + /** + * Sets this button's text. + * + * @param text + * @see #setText(String) + */ + public void setLabel(String text) { + setText(text); + } + + /** + * Gets the text to be presented in the button. + * + * This text does not contain the mnemonic. + * + * @return + */ + public String getText() { + return pText; + } + + /** + * Sets this button's text. Should be a string without mnemonics. + * + * @param text + */ + public void setText(String text) { + pText = text; + setPeerText(); + } + + /** + * Sets the mnemonic character for this button. + * + * @param mnemonic + */ + public void setMnemonic(char mnemonic) { + pMnemonic = mnemonic; + setPeerText(); + } + + /** + * Sets the text configured in this button to its peer. + * + * This method assumes that pText and pMnemonic contain the text + * and mnemonic, respectively. It will then compute the appropriate + * text to be set in SWT's Button. + */ + protected final void setPeerText() { + + // only proceed if there is actually a peer + if (! hasPeer()) + return; + SwingUtilities.invokeSync(new Runnable() { - public void run() { + public void run() { - // Stop if we don't have any cached text - if (pText == null) return; - - // Strip out any HTML - if (pText.indexOf("<") != -1) - pText = SwingWTUtils.removeHTML(pText); - - // If we don't have a mnemonic, don't do anything - if (pMnemonic == ' ') return; - String text = ( (!SwingWTUtils.isSWTControlAvailable(ppeer)) ? pText : ppeer.getText()); - - // Sort out the tooltip for the mnemonic if this is a push button - // of some type (check/radio is more obviously visible) - if (me instanceof JToggleButton || me instanceof JButton) - if (pToolTipText.indexOf("(ALT+") == -1) { - pToolTipText += " (ALT+" + new String(new char[] { pMnemonic }).toUpperCase()+ ")"; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) - peer.setToolTipText(pToolTipText); - } - }); - } - - // If there is already a mnemonic, remove it - if (text.indexOf("&") != -1) { - text = SwingWTUtils.replace(text, "&", ""); - } - - // If there is no text, then set the text to just be the mnemonic - if (text.equals("")) { - pText = "&" + new String(new char[] {pMnemonic}).toLowerCase(); - if (SwingWTUtils.isSWTControlAvailable(ppeer)) ppeer.setText(text); - } - else { - // Convert the mnemonic and text to a lower case string to make - // the match case insensitive - String lower = text.toLowerCase(); - String mn = new String(new char[] { pMnemonic }).toLowerCase(); - int pos = lower.indexOf(mn); + + String mnemonic = pMnemonic == ' ' ? null : "&" + new String(new char[] { pMnemonic }).toLowerCase(); + + String text = SwingWTUtils.removeHTML(pText); + + // if pText was modified, it means it has some HTML in it + if (null == pText || pText.equals(text)) + containsHTML = false; + else + containsHTML = true; + + if (null == pText && null == mnemonic) { + // no mnemonic, no text + text = ""; + + } else if (mnemonic == null) { + // no mnemonic, but text, defaults to pText + + } else if (null == pText) { + // mnemonic, but no text + text = mnemonic; + + } else { + // both mnemonic and text - if (pos != -1) { - text = text.substring(0, pos) + "&" + text.substring(pos, text.length()); - pText = text; - if (SwingWTUtils.isSWTControlAvailable(ppeer)) ppeer.setText(text); - } - } + // first cleanup text off mnemonics, if it has any + if (text.indexOf("&") != -1) + text = SwingWTUtils.replace(text, "&", ""); + + // now find the mnemonic in the text; use lower case for case insensitive match + int pos = text.toLowerCase().indexOf(mnemonic); + if (pos != -1) + text = text.substring(0, pos) + "&" + text.substring(pos, text.length()); + } + + // Now finally set the text + ppeer.setText(text); + + // And if there is a mnemonic, make sure that the tooltip is set + // TODO - this code should probably not be here, we do not need to always set the tooltip when setting text. + if (null != mnemonic) + setToolTipText(pToolTipText); } }); } + + /** + * Returns the string that will actually be showing in the button. + * + * This code should be kept in sync with {@link #setPeerText()}. + * + * @return + */ + protected final String getShowingText() { + String text = SwingWTUtils.removeHTML(pText); + if (null == text) + return ""; + return SwingWTUtils.replace(text, "&", ""); + } + + /** + * Is the button showing any text at all? + * + * @return + */ + protected final boolean hasShowingText() { + return ! isEmpty(getShowingText()); + } + + /** + * Simply checks whether this text is empty or not. + * + * @param text + * @return + */ + protected final boolean isEmpty(String text) { + return null == text || text.length() == 0; + } - public abstract boolean isSelected(); - public abstract void setSelected(boolean b); - /** Sets the tooltip text used on the component - overridden here, * so that if we have a mnemonic, we can tack it on the end. Only applies * to JButton and JToggleButton */ @@ -278,38 +793,422 @@ if (pToolTipText.indexOf("(ALT+") == -1) pToolTipText += " (ALT+" + new String(new char[] { pMnemonic }).toUpperCase()+ ")"; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(peer)) - peer.setToolTipText(pToolTipText); - } - }); + if (hasPeer()) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + peer.setToolTipText(pToolTipText); + } + }); } - - public void setModel(ButtonModel m) { pModel = m; } - public ButtonModel getModel() { return pModel; } - public void setGroup(ButtonGroup g) { pGroup = g; } - public void doClick() - { - processActionEvent(0); + /** + * Sets a new model for this button. + * + * @param m + */ + public void setModel(ButtonModel m) { + pModel = m; + } + + /** + * Gets this button's model + * + * @return + */ + public ButtonModel getModel() { + return pModel; + } + + /** + * Simulates a mouse clicking this button for a standard amount + * of time. + */ + public void doClick() { + this.doClick(68); } - public void doClick(int pressTime) - { - //TODO: implement the pressTime ( the time the Button is in it's press state) - processActionEvent(0); + /** + * Simulates a mouse clicking this button and waiting pressTime miliseconds + * between pressing and releasing the mouse button. + * + * @param pressTime + */ + public void doClick(int pressTime) { + this.down(); + + try { + Thread.sleep(pressTime); + } catch(InterruptedException ie) { + } + + // change state + this.changeState(); + + this.up(); } - public ActionListener[] getActionListeners() - { - int s = actionListeners.size(); - ActionListener[] f = new ActionListener[s]; - for (int i = 0;i*/ _getChangeListeners() { + if (null == changeListeners) + changeListeners = new Vector/**/(); + return changeListeners; + } + + public void addItemListener(ItemListener l) { + _getItemListeners().add(l); + } + + public void removeItemListener(ItemListener l) { + _getItemListeners().remove(l); + } + + public List/**/ _getItemListeners() { + if (null == itemListeners) + itemListeners = new Vector/**/(); + return itemListeners; + } + + public void addActionListener(ActionListener l) { + _getActionListeners().add(l); + } + + public void removeActionListener(ActionListener l) { + _getActionListeners().remove(l); + } + + public List/**/ _getActionListeners() { + if (null == actionListeners) + actionListeners = new Vector/**/(); + return actionListeners; + } + + + // SIZE + + /** + * Overridden to calculate non-realized preferred size. + */ + protected Dimension calculatePreferredSize() { + Insets i = pMargin; + if (null == i) + i = createDefaultMargin(); + + Dimension size = new Dimension(i.left + i.right, i.top + i.bottom); + + // Uses only the default icon in the calculation + // TODO - perhaps use the "icon in use"? + if (hasDefaultIcon()) { + int heightPadding = Math.max(size.height, 10); + int widthPadding = Math.max(size.width, 10); + Icon icon = getIcon(); + size.height = icon.getIconHeight() + heightPadding; + size.width = icon.getIconWidth() + widthPadding; + } + + String text = getShowingText(); + boolean hasText = ! isEmpty(text); + + if (hasText) { + // this code assumes that the text is side-by-side with the icon... + size.height = Math.max(size.height, SwingWTUtils.getRenderStringHeight(text) + Math.max(i.top + i.bottom, 2)); + size.width += SwingWTUtils.getRenderStringWidth(text); + } + + adjust(size, hasText, hasDefaultIcon()); + + //setSize(size); + return size; + } + + /** + * Allow sub-types to perform some adjustments to the calculated preferred size. + */ + protected void adjust(Dimension size, boolean hasText, boolean hasIcon) { + if (hasText) { + if (hasIcon) + size.width -= 2; + else + size.width += 2; + } + } + + /** + * Override computing the preferred size, because we'd rather calculate + * an estimate ourselves when we have an icon. + * + * @return + */ + protected Dimension computePreferredSize() { + return calculatePreferredSize(); + } + + // HELPERS + + /** + * Simple toString to help debugging. + * + * @return + */ + public String toString() { + return pText; + } + + // ACCESSIBILITY + + /** + * + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ + protected abstract class AccessibleAbstractButton extends AccessibleJComponent { + //implements AccessibleAction, AccessibleValue, AccessibleText, AccessibleExtendedComponent { + + } + + // DEBUG SUPPORT + + /** + * Sub-types can override this to provide a better identifier during debug. + * + * @return + */ + public String debugId() { + StringBuilder b = new StringBuilder(super.debugId()); + + String text = getShowingText(); + + if (null != icons) { + b.append(" [*"); + if (text.length() > 0) + b.append(" \"").append(text).append("\""); + return b.append("]").toString(); + } + + if (text.length() > 0) + b.append(" [\"").append(text).append("\"]"); + + return b.toString(); + } } Index: src/swingwtx/swing/JInternalFrame.java =================================================================== --- src/swingwtx/swing/JInternalFrame.java (revision 85) +++ src/swingwtx/swing/JInternalFrame.java (working copy) @@ -16,6 +16,7 @@ import swingwt.awt.*; import swingwtx.swing.event.*; +import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.*; import java.beans.PropertyVetoException; @@ -274,7 +275,7 @@ public void setSwingWTParent(Container parent) throws Exception { descendantHasPeer = true; disposed = false; - ppeer = new org.eclipse.swt.widgets.Composite(parent.getComposite(), 0); + ppeer = new org.eclipse.swt.widgets.Composite(parent.getComposite(), SWT.NO_RADIO_GROUP); peer = ppeer; composite = ppeer; this.parent = parent; Index: src/swingwtx/swing/JRadioButton.java =================================================================== --- src/swingwtx/swing/JRadioButton.java (revision 85) +++ src/swingwtx/swing/JRadioButton.java (working copy) @@ -12,68 +12,90 @@ package swingwtx.swing; -import org.eclipse.swt.widgets.*; -import org.eclipse.swt.*; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Button; -import swingwt.awt.event.*; +import swingwt.awt.Dimension; +import swingwt.awt.Insets; +import swingwtx.accessibility.AccessibleContext; -import java.util.*; +public class JRadioButton extends JToggleButton implements ButtonModel, SwingConstants { + + public JRadioButton() { + super(); + } -public class JRadioButton extends swingwtx.swing.AbstractButton implements ButtonModel, SwingConstants { - - /** boolean thread safe accessor */ - private boolean bRetVal; - - public JRadioButton() {this(""); } - public JRadioButton(String text) { this(text, false); } - public JRadioButton(String text, Icon icon) { this(text, false); } - public JRadioButton(String text, boolean selected) { pSelection = selected; pText = text; setModel(this); showMnemonic(); } - - /** - * Sends mouse events to component listeners - * Overriden from Component to handle ItemEvents - */ - public void processMouseEvent(MouseEvent e) { - Iterator i = mouseListeners.iterator(); - int eventID = e.getID(); - while (i.hasNext()) { - MouseListener ml = (MouseListener) i.next(); - if (eventID == MouseEvent.MOUSE_CLICKED) { ml.mouseClicked(e); processItemEvent(); } - if (eventID == MouseEvent.MOUSE_ENTERED) ml.mouseEntered(e); - if (eventID == MouseEvent.MOUSE_EXITED) ml.mouseExited(e); - if (eventID == MouseEvent.MOUSE_PRESSED) ml.mousePressed(e); - if (eventID == MouseEvent.MOUSE_RELEASED) ml.mouseReleased(e); - } - } - - /** - * Sends KeyEvents to component listeners - * Overriden from Component to handle ItemEvents - */ - public void processKeyEvent(KeyEvent e) { - Iterator i = keyListeners.iterator(); - while (i.hasNext()) { - KeyListener ml = (KeyListener) i.next(); - if (e.eventID == KeyEvent.PRESSED) { ml.keyTyped(e); processItemEvent(); } - if (e.eventID == KeyEvent.RELEASED) ml.keyReleased(e); - if (e.eventID == KeyEvent.PRESSED) ml.keyPressed(e); - } - } + public JRadioButton(String text) { + super(text); + } - /** Overriden to calculate non-realised - * preferred size. - */ + public JRadioButton(String text, Icon icon) { + super(text, icon); + } + + public JRadioButton(String text, boolean selected) { + super(text, selected); + } + + public JRadioButton(Icon icon) { + super(icon); + } + + public JRadioButton(Action a) { + super(a); + } + + public JRadioButton(Icon icon, boolean selected) { + super(icon, selected); + } + + public JRadioButton(String text, Icon icon, boolean selected) { + super(text, icon, selected); + } + + /** + * Overridden to calculate non-realized preferred size. + *//* protected swingwt.awt.Dimension calculatePreferredSize() { - // Use the text height/width + 2 pixels for - // borders and an extra 8 pixels for the radio itself. - swingwt.awt.Dimension size = new swingwt.awt.Dimension( - SwingWTUtils.getRenderStringWidth(pText) + 10, - SwingWTUtils.getRenderStringHeight(pText) + 6); + + Dimension size = + (null != pIcon) ? + // if there's an icon, use the icon's size because we're using Toggle buttons + new Dimension(pIcon.getIconWidth(), pIcon.getIconHeight()) : + + // Use the text height/width + 2 pixels for + // borders and an extra 8 pixels for the radio itself. + new Dimension( + SwingWTUtils.getRenderStringWidth(pText) + 10, + SwingWTUtils.getRenderStringHeight(pText) + 6); setSize(size); return size; } + /** + * Override computing the preferred size, because we'd rather calculate + * an estimate ourselves when we have an icon. + * + * @return + *//* + protected Dimension computePreferredSize() { + if (null != pIcon) + return calculatePreferredSize(); + + return super.computePreferredSize(); + }*/ + /** + * Creates the default margin for buttons. + * + * @return + */ + protected Insets createDefaultMargin() { + // This is the default margin with the basic UI in Java 1.6. + // It may vary depending on platforms and L&F + return new Insets(3, 0, 3, 5); + } + /** * Once a parent component receives an "add" call for a child, this being * the child, this should be called to tell us to instantiate the peer @@ -81,57 +103,49 @@ */ public void setSwingWTParent(swingwt.awt.Container parent) throws Exception { descendantHasPeer = true; - ppeer = new Button(parent.getComposite(), SWT.RADIO); - ppeer.setText(pText); - ppeer.setSelection(pSelection); - ppeer.setAlignment(SwingWTUtils.translateSwingAlignmentConstant(pVAlign) | + if (! hasDefaultIcon()) { + ppeer = new Button(parent.getComposite(), SWT.RADIO | SWT.LEFT); + toggle = false; + } else { + // Radio buttons do not show images properly in SWT (they show images on the side). + // So we try to use a toggle. It is still ugly because we cannot remove the border + // of the toggle button, and it does not expand properly, but it is better than + // a Radio button. + // The appropriate solution here is to use a composite and draw the icon on it. + // But then we have to fix AbstractButton because it expects a Button as ppeer. + ppeer = new Button(parent.getComposite(), SWT.TOGGLE); + } + + ppeer.setAlignment( + SwingWTUtils.translateSwingAlignmentConstant(pVAlign) | SwingWTUtils.translateSwingAlignmentConstant(pHAlign)); peer = ppeer; this.parent = parent; } - public boolean isSelected() { - bRetVal = false; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (!SwingWTUtils.isSWTControlAvailable(ppeer)) bRetVal = pSelection; else bRetVal = ppeer.getSelection(); - } - }); - return bRetVal; + protected void adjust(Dimension size, boolean hasText, boolean hasIcon) { + + if (! hasIcon) { + // for the radio icon + size.width += 10; + } } - public void setSelected(final boolean b) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(ppeer)) ppeer.setSelection(b); else pSelection = b; - } - }); - processItemEvent(); - } - - public Object[] getSelectedObjects() { - return null; - } - - public boolean isArmed() { - return false; - } - - public boolean isPressed() { - return false; - } - - public boolean isRollover() { - return false; - } - - public void setArmed(boolean b) { - } - - public void setPressed(boolean b) { - } - - public void setRollover(boolean b) { - } - + /** + * Sub-types should override this method to create the appropriate + * accessible context for the object. + * + * @return a newly created accessible context + */ + protected AccessibleContext createAccessibleContext() { + return new AccessibleJRadioButton(); + } + + /** + * An implementation of AccessibleContext, which should be extended by sub-types. + * + * @author Thiago Tonelli Bartolomei + */ + protected class AccessibleJRadioButton extends AccessibleAbstractButton { + } } Index: src/swingwtx/swing/JSplashScreen.java =================================================================== --- src/swingwtx/swing/JSplashScreen.java (revision 85) +++ src/swingwtx/swing/JSplashScreen.java (working copy) @@ -53,7 +53,9 @@ shell = new Shell(SwingWTUtils.getDisplay(), SWT.NO_TRIM); shell.setSize(data.width, data.height); - + // register the shell + SwingWTUtils.registerWrapper(this, shell); + Rectangle rect = SwingWTUtils.getDisplay().getBounds(); int shellX = (rect.width - data.width) / 2; int shellY = (rect.height - data.height) / 2; Index: src/swingwtx/swing/JColorChooser.java =================================================================== --- src/swingwtx/swing/JColorChooser.java (revision 85) +++ src/swingwtx/swing/JColorChooser.java (working copy) @@ -11,11 +11,17 @@ package swingwtx.swing; -import swingwt.awt.*; -import org.eclipse.swt.widgets.*; -import org.eclipse.swt.*; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.ColorDialog; +import org.eclipse.swt.widgets.Shell; +import swingwt.awt.Color; +import swingwt.awt.Component; +import swingwt.awt.HeadlessException; +import swingwt.awt.event.ActionListener; + /** * JColorChooser cannot descend a Swing component in SWT as it is not * an embeddable widget. Given time, we could develop one from scratch @@ -49,4 +55,73 @@ } + /** + * + * TODO Comment!! + * + * @param b + */ + public void setDragEnabled(boolean b) { + + } + + /** + * + * TODO Comment!! + * + * @return + */ + public Color getColor() { + return initialColor; + } + + /** + * + * TODO Comment!! + * + * @param c + * @param title + * @param modal + * @param chooserPane + * @param okListener + * @param cancelListener + * @return + */ + public static JDialog createDialog(Component c, String title, boolean modal, + JColorChooser chooserPane, ActionListener okListener, + ActionListener cancelListener) { + return null; + //return chooserPane.new ColorChooserDialog(c, title, modal, okListener, cancelListener); + } + + class ColorChooserDialog extends JDialog { + ColorDialog dialog; + ActionListener okListener; + ActionListener cancelListener; + + /** + * TODO Comment!! + * + */ + public ColorChooserDialog(Component c, String title, boolean modal, ActionListener okListener, ActionListener cancelListener) { + this.peer = new Shell(c.getSWTPeer().getShell(), SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); + this.dialog = new ColorDialog(c.getSWTPeer().getShell(), SWT.EMBEDDED); + dialog.setRGB(initialColor.getSWTColor().getRGB()); + this.okListener = okListener; + this.cancelListener = cancelListener; + } + + public void show() { + //peer.open(); + RGB rgb = dialog.open(); + if (null == rgb) { + if (null != cancelListener) { + cancelListener.actionPerformed(null); + } + } else { + JColorChooser.this.initialColor = new swingwt.awt.Color(rgb.red, rgb.green, rgb.blue); + okListener.actionPerformed(null); + } + } + } } Index: src/swingwtx/swing/JMenuBar.java =================================================================== --- src/swingwtx/swing/JMenuBar.java (revision 85) +++ src/swingwtx/swing/JMenuBar.java (working copy) @@ -41,7 +41,7 @@ comps.add(c); if (menu != null) { c.setSwingWTParent(menu, shell); - c.setCachedProperties(); + c.assertCachedProperties(); c.registerEvents(); } } Index: src/swingwtx/swing/JOptionPane.java =================================================================== --- src/swingwtx/swing/JOptionPane.java (revision 85) +++ src/swingwtx/swing/JOptionPane.java (working copy) @@ -12,11 +12,18 @@ package swingwtx.swing; -import org.eclipse.swt.widgets.*; -import org.eclipse.swt.*; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; -import swingwt.awt.*; -import swingwt.awt.event.*; +import swingwt.awt.BorderLayout; +import swingwt.awt.Component; +import swingwt.awt.Container; +import swingwt.awt.Dimension; +import swingwt.awt.Frame; +import swingwt.awt.Toolkit; +import swingwt.awt.event.ActionEvent; +import swingwt.awt.event.ActionListener; // TODO: all showXXX methods should take swingwt.awt.Component instead of Container @@ -184,56 +191,53 @@ // showConfirmdialog is changed and added some Title and Icon (null) // TODO Fix the icon - public static int showConfirmDialog(swingwt.awt.Container parent, Object message) { + public static int showConfirmDialog(swingwt.awt.Component parent, Object message) { return showConfirmDialog(parent, message, "", QUESTION_MESSAGE); } - public static int showConfirmDialog(swingwt.awt.Container parent, Object message, String title, int messageType) { + public static int showConfirmDialog(swingwt.awt.Component parent, Object message, String title, int messageType) { return showConfirmDialog(parent, message, title, 0, messageType); } - public static int showConfirmDialog(final swingwt.awt.Container parent, final Object message, final String title, final int messageType, final int buttons) { + public static int showConfirmDialog(final swingwt.awt.Component parent, final Object message, final String title, final int messageType, final int buttons) { return showConfirmDialog(parent, message, title, buttons,messageType,null); } - public static int showConfirmDialog(final swingwt.awt.Container parent, final Object message, + public static int showConfirmDialog(final swingwt.awt.Component parent, final Object message, final String title, final int buttons, final int messageType, final Icon icon) { confRetVal = 0; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - Shell container = getModalParent(parent); - MessageBox m = new MessageBox(container, messageType | SWT.YES | SWT.NO); - m.setMessage(getOptionPaneMessage(message)); - m.setText(title); - - confRetVal = m.open(); - switch (confRetVal) { - case SWT.YES: confRetVal = YES_OPTION; break; - case SWT.NO: confRetVal = NO_OPTION; break; - } - } - }); + if (parent instanceof Container) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + Shell container = getModalParent((Container) parent); + MessageBox m = new MessageBox(container, messageType | SWT.YES | SWT.NO); + m.setMessage(getOptionPaneMessage(message)); + m.setText(title); + + confRetVal = m.open(); + switch (confRetVal) { + case SWT.YES: confRetVal = YES_OPTION; break; + case SWT.NO: confRetVal = NO_OPTION; break; + } + } + }); return confRetVal; } - public static void showMessageDialog(swingwt.awt.Container parent, Object message) { + public static void showMessageDialog(swingwt.awt.Component parent, Object message) { showMessageDialog(parent, message, "Message", SWT.ICON_INFORMATION); } - - // TODO: all showXXX methods should take swingwt.awt.Component instead of Container - public static void showMessageDialog(final swingwt.awt.Component parent, final Object message, final String title, final int messageType) { - showMessageDialog((Container) parent, message, title, messageType); - } /** FIXME: Where the fuck is the title? */ - public static void showMessageDialog(final swingwt.awt.Container parent, final Object message, final String title, final int messageType) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - MessageBox m = new MessageBox(getModalParent(parent), messageType | SWT.OK); - m.setMessage(getOptionPaneMessage(message)); - m.setText(title); - m.open(); - } - }); + public static void showMessageDialog(final swingwt.awt.Component parent, final Object message, final String title, final int messageType) { + if (parent instanceof Container) + SwingUtilities.invokeSync(new Runnable() { + public void run() { + MessageBox m = new MessageBox(getModalParent((Container) parent), messageType | SWT.OK); + m.setMessage(getOptionPaneMessage(message)); + m.setText(title); + m.open(); + } + }); } // Internal fake to ordinary messageDialog public static void showInternalMessageDialog(swingwt.awt.Container parent, Object message) { @@ -245,7 +249,7 @@ public static void showInternalMessageDialog(final swingwt.awt.Container parent, final Object message, final String title, final int messageType) { showMessageDialog(parent,message,title,messageType); } - public static String showInputDialog(swingwt.awt.Container parent, Object message) { + public static String showInputDialog(swingwt.awt.Component parent, Object message) { SwingStyleInputDialog dlg = new SwingStyleInputDialog(parent, getOptionPaneMessage(message), "Input", 0, null, null, null); dlg.show(); if (lastInputDialogReturnValue == null) @@ -253,7 +257,7 @@ else return lastInputDialogReturnValue.toString(); } - public static String showInputDialog(swingwt.awt.Container parent, Object message, Object initialSelectionValue) { + public static String showInputDialog(swingwt.awt.Component parent, Object message, Object initialSelectionValue) { SwingStyleInputDialog dlg = new SwingStyleInputDialog(parent, getOptionPaneMessage(message), "Input", 0, null, null, initialSelectionValue); dlg.show(); if (lastInputDialogReturnValue == null) @@ -281,7 +285,7 @@ return lastInputDialogReturnValue; } - public static int showOptionDialog(final swingwt.awt.Container parent, final Object message, final String title, final int optionType, final int messageType, + public static int showOptionDialog(final swingwt.awt.Component parent, final Object message, final String title, final int optionType, final int messageType, final Icon icon, final Object[] options, final Object initialValue) { SwingUtilities.invokeSync(new Runnable() { public void run() { Index: src/swingwtx/swing/JToggleButton.java =================================================================== --- src/swingwtx/swing/JToggleButton.java (revision 85) +++ src/swingwtx/swing/JToggleButton.java (working copy) @@ -8,45 +8,80 @@ Contact me by electronic mail: bobintetley@users.sourceforge.net */ - - package swingwtx.swing; -import org.eclipse.swt.widgets.*; -import org.eclipse.swt.*; +import java.util.Iterator; -import swingwt.awt.event.*; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Button; -import java.util.*; +import swingwt.awt.Dimension; +import swingwt.awt.event.KeyEvent; +import swingwt.awt.event.KeyListener; +import swingwt.awt.event.MouseEvent; +import swingwt.awt.event.MouseListener; -public class JToggleButton extends swingwtx.swing.AbstractButton implements ButtonModel, SwingConstants { +public class JToggleButton extends AbstractButton implements SwingConstants { - protected Icon pImage = null; + /** + * A custom style flag for the SWT Button + */ + protected int customStyle = 0; + + /** + * Indicates that the TOGGLE flag is used for the peer. + * + * (note that sub-types may use RADIO or CHECK for example. + */ + protected boolean toggle = true; + + public JToggleButton() { + this("", null, false); + } + + public JToggleButton(String text) { + this(text, null, false); + } - /** boolean thread safe accessor */ - private boolean bRetVal; + public JToggleButton(Icon icon) { + this(null, icon, false); + } - public JToggleButton() {this(""); } - public JToggleButton(String text) { pText = text; setModel(this); showMnemonic(); } - public JToggleButton(String text, Icon icon) { pText = text; pImage = icon; setModel(this); showMnemonic(); } + public JToggleButton(Action a) { + this(); + setAction(a); + } - public JToggleButton(String title, boolean selected) { - this(title); - setSelected(selected); + public JToggleButton(String text, Icon icon) { + this(text, icon, false); } - public void setIcon(Icon icon) { - pImage = icon; - final JToggleButton pthis = this; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(ppeer)) - ppeer.setImage(SwingWTUtils.getSWTImageFromSwingIcon(pthis, pImage)); - } - }); + public JToggleButton(String text, boolean selected) { + this(text, null, selected); } + public JToggleButton(Icon icon, boolean selected) { + this("", icon, selected); + } + + public JToggleButton(String text, Icon icon, boolean selected) { + super(); + setText(text); + setIcon(icon); + _setSelected(selected); + } + /** + * This simulates how toggle buttons change their state, + * i.e., they toggle the selected property. + * + * @see AbstractButton#doClick(int) + */ + protected void changeState() { + this._setSelected(! this.isSelected()); + } + + /** * Sends mouse events to component listeners * Overriden from Component to handle ItemEvents */ @@ -77,7 +112,16 @@ } } - protected int customStyle = 0; + /** + * Sets a custom style flag. + * + * This is not part of the Swing API, it is here only so that SwingWT clients + * can instantiate toggle buttons with a different style. + * + * This method should be called prior to adding the toggle button to a container. + * + * @param style + */ public void setCustomSWTStyle(int style) { this.customStyle = style; } @@ -90,54 +134,30 @@ public void setSwingWTParent(swingwt.awt.Container parent) throws Exception { descendantHasPeer = true; ppeer = new Button(parent.getComposite(), SWT.TOGGLE | customStyle); - if (pText != null) ppeer.setText(pText); - ppeer.setSelection(pSelection); - ppeer.setAlignment(pVAlign | pHAlign); + ppeer.setAlignment( + //pVAlign | + pHAlign); peer = ppeer; this.parent = parent; } - public boolean isSelected() { - bRetVal = false; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (!SwingWTUtils.isSWTControlAvailable(ppeer)) bRetVal = false; else bRetVal = ppeer.getSelection(); - } - }); - return bRetVal; - } - - public void setSelected(final boolean b) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(ppeer)) ppeer.setSelection(b); else pSelection = b; - } - }); - } + //@Override + protected Dimension calculatePreferredSize() { - public Object[] getSelectedObjects() { - return null; - } - - public boolean isArmed() { - return false; + // If TOGGLE style is in use and there's no text, only respect explicitly + // user defined margins, otherwise use the icon's size + if (toggle && hasDefaultIcon() && ! hasShowingText()) { + Dimension size = new Dimension(); + if (pMargin != null) { + size.height = pMargin.top + pMargin.bottom; + size.width = pMargin.left + pMargin.right; + } + Icon icon = getIcon(); + size.height += icon.getIconHeight(); + size.width += icon.getIconWidth(); + return size; + } + + return super.calculatePreferredSize(); } - - public boolean isPressed() { - return false; - } - - public boolean isRollover() { - return false; - } - - public void setArmed(boolean b) { - } - - public void setPressed(boolean b) { - } - - public void setRollover(boolean b) { - } - } Index: src/swingwtx/swing/JCheckBox.java =================================================================== --- src/swingwtx/swing/JCheckBox.java (revision 85) +++ src/swingwtx/swing/JCheckBox.java (working copy) @@ -12,51 +12,66 @@ package swingwtx.swing; -import org.eclipse.swt.widgets.*; -import org.eclipse.swt.*; +import java.util.Iterator; -import swingwt.awt.event.*; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Button; -import java.util.*; +import swingwt.awt.Dimension; +import swingwt.awt.Insets; +import swingwt.awt.event.KeyEvent; +import swingwt.awt.event.KeyListener; +import swingwtx.accessibility.Accessible; -public class JCheckBox extends swingwtx.swing.AbstractButton implements ButtonModel, SwingConstants { - - /** boolean thread safe accessor */ - private boolean bRetVal; +public class JCheckBox extends JToggleButton implements SwingConstants, Accessible { /** AWT uses Checkboxes for radio buttons as well **/ private boolean isAWTRadio = false; - - public JCheckBox() {this(""); } - public JCheckBox(String text) { this(text, false); } - public JCheckBox(String text, Icon icon) { this(text, false); } - public JCheckBox(String text, boolean selected) { pText = text; pSelection = selected; setModel(this); showMnemonic();} - /** This constructor is used for AWT CheckboxGroup support **/ - public JCheckBox(String text, boolean selected, ButtonGroup bg) { pText = text; pSelection = selected; isAWTRadio = true; setModel(this); showMnemonic();} - - + + public JCheckBox() { + super(); + } + + public JCheckBox(Icon icon) { + super(icon); + } + + public JCheckBox(Icon icon, boolean selected) { + super(icon, selected); + } + + public JCheckBox(String text) { + super(text); + } + + public JCheckBox(Action a) { + super(a); + } + + public JCheckBox(String text, boolean selected) { + super(text, selected); + } + + public JCheckBox(String text, Icon icon) { + super(text, icon); + } + + public JCheckBox(String text, Icon icon, boolean selected) { + super(text, icon, selected); + } + + /** This constructor is used for AWT CheckboxGroup support **/ + public JCheckBox(String text, boolean selected, ButtonGroup bg) { + super(text, selected); + isAWTRadio = true; + } + /** - * Sends mouse events to component listeners - * Overriden from Component to handle ItemEvents - */ - public void processMouseEvent(MouseEvent e) { - Iterator i = mouseListeners.iterator(); - while (i.hasNext()) { - MouseListener ml = (MouseListener) i.next(); - int eventID = e.getID(); - if (eventID == MouseEvent.MOUSE_CLICKED) {ml.mouseClicked(e); processItemEvent(); } - if (eventID == MouseEvent.MOUSE_ENTERED) ml.mouseEntered(e); - if (eventID == MouseEvent.MOUSE_EXITED) ml.mouseExited(e); - if (eventID == MouseEvent.MOUSE_PRESSED) ml.mousePressed(e); - if (eventID == MouseEvent.MOUSE_RELEASED) ml.mouseReleased(e); - } - } - - /** * Sends KeyEvents to component listeners * Overriden from Component to handle ItemEvents */ public void processKeyEvent(KeyEvent e) { + // TODO - this is very close to JToggleButton.processKeyEvent. Check if we need this... Iterator i = keyListeners.iterator(); while (i.hasNext()) { KeyListener ml = (KeyListener) i.next(); @@ -68,7 +83,7 @@ /** Overriden to calculate non-realised * preferred size. - */ + *//* protected swingwt.awt.Dimension calculatePreferredSize() { // Use the text height/width + 6 pixels for // borders and an extra 8 pixels for the checkbox itself. @@ -77,73 +92,50 @@ SwingWTUtils.getRenderStringHeight(pText) + 6); setSize(size); return size; - } + }*/ /** * Once a parent component receives an "add" call for a child, this being * the child, this should be called to tell us to instantiate the peer * and load in any cached properties. + * + * @see JRadioButton#setSwingWTParent */ public void setSwingWTParent(swingwt.awt.Container parent) throws Exception { descendantHasPeer = true; - if (isAWTRadio) { - ppeer = new Button(parent.getComposite(), SWT.RADIO); + if (! hasDefaultIcon()) { + toggle = false; + if (isAWTRadio) { + ppeer = new Button(parent.getComposite(), SWT.RADIO); + } else { + ppeer = new Button(parent.getComposite(), SWT.CHECK); + } } else { - ppeer = new Button(parent.getComposite(), SWT.CHECK); + // See JRadioButton#setSwingWTParent + ppeer = new Button(parent.getComposite(), SWT.TOGGLE); } - ppeer.setText(pText); - ppeer.setSelection(pSelection); - ppeer.setAlignment( SwingWTUtils.translateSwingAlignmentConstant(pVAlign) | - SwingWTUtils.translateSwingAlignmentConstant(pHAlign) ); + ppeer.setAlignment( + //SwingWTUtils.translateSwingAlignmentConstant(pVAlign) | + SwingWTUtils.translateSwingAlignmentConstant(pHAlign)); peer = ppeer; this.parent = parent; } - public boolean isSelected() { - bRetVal = false; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (!SwingWTUtils.isSWTControlAvailable(ppeer)) bRetVal = pSelection; else bRetVal = ppeer.getSelection(); - } - }); - return bRetVal; + /** + * Creates the default margin for buttons. + * + * @return + */ + protected Insets createDefaultMargin() { + // This is the default margin with the standard L&F in Java 1.6, GTK for Linux. + // It may vary depending on platforms and L&F + return new Insets(2, 10, 2, 10); } - - public void setSelected(final boolean b) { - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(ppeer)) ppeer.setSelection(b); else pSelection = b; - } - }); + + protected void adjust(Dimension size, boolean hasText, boolean hasIcon) { + if (toggle && ! hasText) { + size.height -= 10; + size.width -= 10; + } } - - public Object[] getSelectedObjects() { - return null; - } - - public int getMnemonic() { - return 0; - } - - public boolean isArmed() { - return false; - } - - public boolean isPressed() { - return false; - } - - public boolean isRollover() { - return false; - } - - public void setArmed(boolean b) { - } - - public void setPressed(boolean b) { - } - - public void setRollover(boolean b) { - } - } Index: src/swingwtx/swing/JTree.java =================================================================== --- src/swingwtx/swing/JTree.java (revision 85) +++ src/swingwtx/swing/JTree.java (working copy) @@ -872,6 +872,15 @@ { // TODO } + /** + * TODO Comment!! + * + * @param dragEnabled + */ + public void setDragEnabled(boolean dragEnabled) { + // TODO Auto-generated method stub + + } } Index: src/swingwtx/swing/DefaultSingleSelectionModel.java =================================================================== --- src/swingwtx/swing/DefaultSingleSelectionModel.java (revision 0) +++ src/swingwtx/swing/DefaultSingleSelectionModel.java (revision 0) @@ -0,0 +1,90 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing; + +import java.util.Iterator; +import java.util.List; +import java.util.Vector; + +import swingwtx.swing.event.ChangeEvent; +import swingwtx.swing.event.ChangeListener; + +/** + * A default implementation of a SwingWT model that supports at most one indexed selection. + * + * @author Thiago Tonelli Bartolomei + */ +public class DefaultSingleSelectionModel implements SingleSelectionModel { + + /** + * The index of currently selected element, or -1 if none. + */ + protected int selectedIndex = -1; + + /** + * A lazy list of change listeners. + */ + protected List/**/ changeListeners = null; + + //@Override + public int getSelectedIndex() { + return selectedIndex; + } + + //@Override + public void setSelectedIndex(int index) { + selectedIndex = index; + processChangeEvent(new ChangeEvent(this)); + } + + //@Override + public void clearSelection() { + this.setSelectedIndex(-1); + } + + //@Override + public boolean isSelected() { + return selectedIndex != -1; + } + + //@Override + public void addChangeListener(ChangeListener listener) { + this.getChangeListeners().add(listener); + } + + //@Override + public void removeChangeListener(ChangeListener listener) { + this.getChangeListeners().remove(listener); + } + + /** + * Gets the list of change listeners, creating a new one if needed. + * + * @return + */ + protected final List/**/ getChangeListeners() { + if (null == changeListeners) + changeListeners = new Vector/**/(); + return changeListeners; + } + + /** + * Process change events + */ + protected final void processChangeEvent(ChangeEvent e) { + if (null != changeListeners) { + Iterator i = changeListeners.iterator(); + while(i.hasNext()) + ((ChangeListener) i.next()).stateChanged(e); + } + /* + for (ChangeListener l : changeListeners) + l.stateChanged(e); + */ + } +} Index: src/swingwtx/swing/filechooser/FileNameExtensionFilter.java =================================================================== --- src/swingwtx/swing/filechooser/FileNameExtensionFilter.java (revision 0) +++ src/swingwtx/swing/filechooser/FileNameExtensionFilter.java (revision 0) @@ -0,0 +1,44 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing.filechooser; + +import java.io.File; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class FileNameExtensionFilter extends FileFilter { + + public FileNameExtensionFilter(String description, String[] extensions) { + + } + + /** + * TODO Comment!! + * + * @param f + * @return + */ + public boolean accept(File f) { + // TODO Auto-generated method stub + return false; + } + + /** + * TODO Comment!! + * + * @return + */ + public String getDescription() { + // TODO Auto-generated method stub + return null; + } + +} Index: src/swingwtx/swing/filechooser/FileView.java =================================================================== --- src/swingwtx/swing/filechooser/FileView.java (revision 0) +++ src/swingwtx/swing/filechooser/FileView.java (revision 0) @@ -0,0 +1,17 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing.filechooser; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public abstract class FileView { + +} Index: src/swingwtx/swing/JList.java =================================================================== --- src/swingwtx/swing/JList.java (revision 85) +++ src/swingwtx/swing/JList.java (working copy) @@ -462,6 +462,16 @@ } /** + * + * TODO Comment!! + * + * @param b + */ + public void setDragEnabled(boolean b) { + + } + + /** * Assigns events to the peer for selection so that we can update the * ListSelectionModel for this component. */ Index: src/swingwtx/swing/table/TableRowSorter.java =================================================================== --- src/swingwtx/swing/table/TableRowSorter.java (revision 0) +++ src/swingwtx/swing/table/TableRowSorter.java (revision 0) @@ -0,0 +1,23 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing.table; + +import swingwtx.swing.DefaultRowSorter; + + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class TableRowSorter extends DefaultRowSorter { + + public TableRowSorter(Object model) { + + } +} Index: src/swingwtx/swing/JToolBar.java =================================================================== --- src/swingwtx/swing/JToolBar.java (revision 85) +++ src/swingwtx/swing/JToolBar.java (working copy) @@ -260,7 +260,7 @@ this.parent = parent; - ppeer = new org.eclipse.swt.widgets.Composite(parent.getComposite(), SWT.NONE); + ppeer = new org.eclipse.swt.widgets.Composite(parent.getComposite(), SWT.NO_RADIO_GROUP); lastAdd = ppeer; peer = ppeer; composite = ppeer; @@ -399,7 +399,7 @@ // Assign the component onto the container, // set it's base properties and register all its events c.setSwingWTParent(me); - c.setCachedProperties(); + c.assertCachedProperties(); c.registerEvents(); } catch (Exception e) { Index: src/swingwtx/swing/SwingWTUtils.java =================================================================== --- src/swingwtx/swing/SwingWTUtils.java (revision 85) +++ src/swingwtx/swing/SwingWTUtils.java (working copy) @@ -12,23 +12,28 @@ package swingwtx.swing; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; +import java.util.Vector; +import java.util.WeakHashMap; + import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Path; -import org.eclipse.swt.widgets.*; +import org.eclipse.swt.widgets.Display; import swingwt.awt.Component; -import swingwt.awt.Container; -import swingwt.awt.Dimension; +import swingwt.awt.Image; import swingwt.awt.Shape; import swingwt.awt.geom.PathIterator; -import swingwt.awt.Image; - -import java.io.*; -import java.net.*; -import java.util.*; -import java.lang.reflect.*; - /** * Utilities required for SwingWT. Handles management * of SWT display, SwingWT event pump and some handy stuff @@ -372,6 +377,8 @@ */ public static synchronized void stopEventDispatchRunning() { eventsDispatching = false; + if (null != display) + display.wake(); } private static class InvalidateQueue implements Runnable { @@ -815,8 +822,13 @@ /*** Removes HTML tags from a string * @param s The string to remove HTML tags from */ - public static String removeHTML(String s, boolean replaceNewlines) { + public static String removeHTML(final String text, boolean replaceNewlines) { + if (null == text) + return null; + + String s = text; + // If we have an opener and no closer, then // it ain't HTML and we shouldn't break it int opener = s.indexOf("<"); @@ -846,6 +858,10 @@ s = replace(s, "<", "<"); s = replace(s, ">", ">"); + // Only compress whitespace if HTML was found + if (text.equals(s)) + return s; + // Compress whitespace s = s.trim(); StringBuffer o = new StringBuffer(); @@ -936,6 +952,32 @@ return ico; } + /** + * A very simplistic wrapping identity map + */ + protected static Map map = new WeakHashMap(); + + /** + * Register that this SwingWT wrapper wraps this peer. + * + * @param wrapper + * @param peer + */ + public static void registerWrapper(Object wrapper, Object peer) { + map.put(peer, wrapper); + } + + /** + * Gets the SwingWT wrapper for this peer. + * + * @param peer + * @return null if there is no wrapper registered. + */ + public static Object wrap(Object peer) { + if (map.containsKey(peer)) + return map.get(peer); + return null; + } } Index: src/swingwtx/swing/DefaultBoundedRangeModel.java =================================================================== --- src/swingwtx/swing/DefaultBoundedRangeModel.java (revision 0) +++ src/swingwtx/swing/DefaultBoundedRangeModel.java (revision 0) @@ -0,0 +1,27 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing; + +import java.io.Serializable; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class DefaultBoundedRangeModel implements BoundedRangeModel, Serializable { + + /** + * TODO Comment!! + */ + private static final long serialVersionUID = 1L; + + public DefaultBoundedRangeModel(int value, int extent, int min, int max) { + + } +} Index: src/swingwtx/swing/BoxLayout.java =================================================================== --- src/swingwtx/swing/BoxLayout.java (revision 85) +++ src/swingwtx/swing/BoxLayout.java (working copy) @@ -13,195 +13,417 @@ import swingwt.awt.*; +/** + * An implementation of the BoxLayout. + * + * This layout positions components in the X or Y axis. + * + * @author R. Rawson-Tetley + * @author Thiago Tonelli Bartolomei + */ public class BoxLayout implements LayoutManager2 { + /** + * Indicates components should be laid out from left to right. + */ public static final int X_AXIS = 0; + + /** + * Indicates components should be laid out from top to bottom. + */ public static final int Y_AXIS = 1; + + /** + * Indicates components should be laid out in the direction of a line. + * + * @see ComponentOrientation + */ public static final int LINE_AXIS = 2; + + /** + * Indicates components should be laid out in the direction of a page. + * + * @see ComponentOrientation + */ public static final int PAGE_AXIS = 3; - protected SizeRequirements[] childWidth; - protected SizeRequirements[] childHeight; - protected SizeRequirements totalWidth; - protected SizeRequirements totalHeight; + /** + * The current layout axis. + */ + protected final int axis; - private int axis; - private Component target = null; + /** + * The container been managed. + */ + protected final Container target; - public BoxLayout(Component target, int axis) { - if (axis != X_AXIS && axis != Y_AXIS && axis != LINE_AXIS && axis != PAGE_AXIS) { - throw new Error("Invalid axis"); - } - this.axis = axis; - this.target = target; - } + // If any of the following fields is null, it means that the layout is + // invalid and must be recalculated. + + /** + * The computed size requirements for the width of the target's children. + */ + protected SizeRequirements[] childrenWidth = null; - public BoxLayout(Container target, int axis) { - this((Component) target, axis); - } + /** + * The computed size requirements for the height of the target's children. + */ + protected SizeRequirements[] childrenHeight = null; - public synchronized void invalidateLayout(Container target) { - childWidth = null; - childHeight = null; - totalWidth = null; - totalHeight = null; - } + /** + * The computed size requirements for the target container's width. + */ + protected SizeRequirements totalWidth = null; - public void addLayoutComponent(String name, Component comp) { - } + /** + * The computed size requirements for the target container's heigth. + */ + protected SizeRequirements totalHeight = null; - public void removeLayoutComponent(Component comp) { - } - - public void addLayoutComponent(Component comp, Object constraints) { - } - - public Dimension preferredLayoutSize(Container target) { - - calculate(); - Dimension size = null; - if (totalWidth == null) - size = new Dimension(0, 0); - else - size = new Dimension(totalWidth.preferred, totalHeight.preferred); + /** + * Keeps track of the visibility flag of children. + * + * @see #visibilityChanged() + */ + protected boolean[] visibility = null; + + + /** + * Creates a box layout that will manage this container. + * + * @param target + * @param axis + */ + public BoxLayout(Container target, int axis) { + // TODO - There was a constructor that received Component instead of Container, which + // does not seem to make sense. There's probably a reason for that, so that is in fact + // needed, we can easily create a new constructor here. + if (axis != X_AXIS && axis != Y_AXIS && axis != LINE_AXIS && axis != PAGE_AXIS) + throw new Error("Invalid axis"); - Insets insets = target.getInsets(); - size.width = (int) Math.min( (long) size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE); - size.height = (int) Math.min( (long) size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE); - return size; + this.axis = axis; + this.target = target; } + + // LayoutManager implementation - public Dimension minimumLayoutSize(Container target) { - - calculate(); - Dimension size = new Dimension(totalWidth.minimum, totalHeight.minimum); - - Insets insets = target.getInsets(); - size.width = - (int) Math.min( (long) size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE); - size.height = (int) Math.min( (long) size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE); - return size; + /** + * Adds the component to this layout, identifying it by this string. + * + * @param name + * @param component + */ + public void addLayoutComponent(String name, Component component) { + invalidate(); } - public Dimension maximumLayoutSize(Container target) { - - calculate(); - Dimension size = new Dimension(totalWidth.maximum, totalHeight.maximum); - - Insets insets = target.getInsets(); - size.width = - (int) Math.min( (long) size.width + (long) insets.left + (long) insets.right, Integer.MAX_VALUE); - size.height = (int) Math.min( (long) size.height + (long) insets.top + (long) insets.bottom, Integer.MAX_VALUE); - return size; + /** + * Removes the component from this layout. + * + * @param component + */ + public void removeLayoutComponent(Component component) { + invalidate(); } - public synchronized float getLayoutAlignmentX(Container target) { - calculate(); - return totalWidth.alignment; - } - - public synchronized float getLayoutAlignmentY(Container target) { - calculate(); - return totalHeight.alignment; - } - - public void layoutContainer(Container target) { + /** + * Lays out the container. + * + * @param container + */ + public void layoutContainer(Container container) { + //System.out.println("Laying out " + target.debugId()); + + if (needsRecalculation()) + calculate(); + + Dimension alloc = container.getSize(); - Dimension alloc = target.getSize(); - Insets in = target.getInsets(); + Insets in = container.getInsets(); alloc.width -= in.left + in.right; alloc.height -= in.top + in.bottom; + int absoluteAxis = getAbsoluteAxis(container); + + boolean leftToRight = (absoluteAxis != axis) ? container.getComponentOrientation().isLeftToRight() : true; - int absoluteAxis = X_AXIS; + int childrenCount = childrenWidth.length; + int[] xOffsets = new int[childrenCount]; + int[] xSpans = new int[childrenCount]; + int[] yOffsets = new int[childrenCount]; + int[] ySpans = new int[childrenCount]; - if (axis == LINE_AXIS) - absoluteAxis = target.getComponentOrientation().isHorizontal() ? X_AXIS : Y_AXIS; - else if (axis == PAGE_AXIS) - absoluteAxis = target.getComponentOrientation().isHorizontal() ? Y_AXIS : X_AXIS; - else - absoluteAxis = axis; - - boolean ltr = (absoluteAxis != axis) ? target.getComponentOrientation().isLeftToRight() : true; - - // Determine where children go - calculate(); - - int nChildren = childWidth.length; - int[] xOffsets = new int[nChildren]; - int[] xSpans = new int[nChildren]; - int[] yOffsets = new int[nChildren]; - int[] ySpans = new int[nChildren]; - if (absoluteAxis == X_AXIS) { - SizeRequirements.calculateAlignedPositions(alloc.height, totalHeight, childHeight, yOffsets, ySpans); - SizeRequirements.calculateTiledPositions(alloc.width, totalWidth, childWidth, xOffsets, xSpans, ltr); - } - else { - SizeRequirements.calculateTiledPositions(alloc.height, totalHeight, childHeight, yOffsets, ySpans); - SizeRequirements.calculateAlignedPositions(alloc.width, totalWidth, childWidth, xOffsets, xSpans, ltr); + SizeRequirements.calculateAlignedPositions(alloc.height, totalHeight, childrenHeight, yOffsets, ySpans); + SizeRequirements.calculateTiledPositions(alloc.width, totalWidth, childrenWidth, xOffsets, xSpans, leftToRight); + } else { + SizeRequirements.calculateTiledPositions(alloc.height, totalHeight, childrenHeight, yOffsets, ySpans); + SizeRequirements.calculateAlignedPositions(alloc.width, totalWidth, childrenWidth, xOffsets, xSpans, leftToRight); } - for (int i = 0; i < nChildren; i++) { - Component c = target.getComponent(i); + for (int i = 0; i < childrenCount; i++) { + Component c = container.getComponent(i); c.setBounds( - (int) Math.min( (long) in.left + (long) xOffsets[i], Integer.MAX_VALUE), - (int) Math.min( (long) in.top + (long) yOffsets[i], Integer.MAX_VALUE), - xSpans[i], - ySpans[i]); - + (int) Math.min( + (long) in.left + (long) xOffsets[i], + Integer.MAX_VALUE), + (int) Math.min( + (long) in.top + (long) yOffsets[i], + Integer.MAX_VALUE), + xSpans[i], + ySpans[i]); } } + /** + * Computes the size this container should have based on the + * components contained in it. + * + * @param container + * @return + */ + public Dimension preferredLayoutSize(Container container) { + + if (needsRecalculation()) + calculate(); + + return getBoundDimension(container.getInsets(), totalWidth.preferred, totalHeight.preferred); + } + + /** + * Computes the minimum size of this container, based on the + * components contained in it. + * + * @param container + * @return + */ + public Dimension minimumLayoutSize(Container container) { + + if (needsRecalculation()) + calculate(); + + return getBoundDimension(container.getInsets(), totalWidth.minimum, totalHeight.minimum); + } + + // LayoutManager2 implementation + + /** + * Computes the maximum size of this container, based on the + * components in it. + * + * @param container + * @return + */ + public Dimension maximumLayoutSize(Container container) { + + if (needsRecalculation()) + calculate(); + + return getBoundDimension(container.getInsets(), totalWidth.maximum, totalHeight.maximum); + } + + /** + * Adds this component to the manager with this corresponding + * constraint object. + * + * @param component + * @param constraints + */ + public void addLayoutComponent(Component component, Object constraints) { + + invalidate(); + } + + /** + * A value between 0 (origin) and 1 (infinite) that specifies the + * position this container should be aligned with respect to other + * components, in the X axis. Note that 0.5 means center. + * + * @param container + * @return + */ + public float getLayoutAlignmentX(Container container) { + + if (needsRecalculation()) + calculate(); + + return totalWidth.alignment; + } + + /** + * A value between 0 (origin) and 1 (infinite) that specifies the + * position this container should be aligned with respect to other + * components, in the Y axis. Note that 0.5 means center + * + * @param container + * @return + */ + public float getLayoutAlignmentY(Container container) { + + if (needsRecalculation()) + calculate(); + + return totalHeight.alignment; + } + + /** + * The layout manager should invalidate the layout, i.e., it + * should dischard any cached information. + * + * @param container + */ + public void invalidateLayout(Container container) { + + this.invalidate(); + } + + /** + * Removed cached values to force recalculation. + */ + protected void invalidate() { + childrenWidth = null; + childrenHeight = null; + totalWidth = null; + totalHeight = null; + visibility = null; + } + + /** + * Checks whether the layout must be recalculated. + * + * We use this to avoid recalculating the layout when nothing important changed. + * Currently this means that we need recalculation if the layout was invalidated + * or if any child changed its visibility. + * + * @return + * @see #visibilityChanged() + */ + protected boolean needsRecalculation() { + return (null == childrenWidth || visibilityChanged()); + } + + /** + * Sets the visibility flag for the child with this index. + * + * @param childIndex + * @param isVisible + */ + protected final void setVisibility(int childIndex, boolean isVisible) { + visibility[childIndex] = isVisible; + } + + /** + * Checks whether some child changed its visibility flag since the last + * time the layout was calculated. + * + * The algorithm and data structure here is poor, but works for now. We are keeping + * an array of booleans to represent the visibility flags of children. That is bad + * because i) we may need a large array and ii) we may need to iterate the whole + * array to check if any boolean changed. + * + * A better approach would be to use an array of int, and then use each of the 31 + * available bits to represent the flag of a child. This would speed up the check + * (because we can simply perform a bit mask check for all blocks of 31 children) + * and use less space (because we need one int for each 31 children). But this is + * trickier to implement, so I am leaving it for now. + * + * @return + */ + protected final boolean visibilityChanged() { + if (null == visibility) + return true; + + int count = target.getComponentCount(); + if (count != visibility.length) + return true; + + for (int i = 0; i < count; i++) + if (visibility[i] != target.getComponent(i).isVisible()) + return true; + + return false; + } + + /** + * Computes the size requirements for each child component plus for + * the target container. + */ protected void calculate() { - if (!(target instanceof Container)) - return; - Container tg = (Container) target; - int n = tg.getComponentCount(); - childWidth = new SizeRequirements[n]; - childHeight = new SizeRequirements[n]; - for (int i = 0; i < n; i++) { - Component c = tg.getComponent(i); - if (!c.isVisible()) { - childWidth[i] = - new SizeRequirements(0, 0, 0, c.getAlignmentX()); - childHeight[i] = - new SizeRequirements(0, 0, 0, c.getAlignmentY()); - continue; + //System.out.println("Calculating layout " + target.debugId()); + + // Compute the size requirements for each children + int childrenCount = target.getComponentCount(); + childrenWidth = new SizeRequirements[childrenCount]; + childrenHeight = new SizeRequirements[childrenCount]; + + visibility = new boolean[childrenCount]; + + for (int i = 0; i < childrenCount; i++) { + Component child = target.getComponent(i); + + boolean isVisible = child.isVisible(); + setVisibility(i, isVisible); + + if (! isVisible) { + + childrenWidth[i] = new SizeRequirements(0, 0, 0, child.getAlignmentX()); + childrenHeight[i] = new SizeRequirements(0, 0, 0, child.getAlignmentY()); + + } else { + + Dimension pref = child.getPreferredSize(); + Dimension min = child.getMinimumSize(); + Dimension max = child.getMaximumSize(); + + childrenWidth[i] = new SizeRequirements(min.width, pref.width, max.width, child.getAlignmentX()); + childrenHeight[i] = new SizeRequirements(min.height, pref.height, max.height, child.getAlignmentY()); } - Dimension min = c.getMinimumSize(); - Dimension typ = c.getPreferredSize(); - Dimension max = c.getMaximumSize(); - childWidth[i] = - new SizeRequirements( - min.width, - typ.width, - max.width, - c.getAlignmentX()); - childHeight[i] = - new SizeRequirements( - min.height, - typ.height, - max.height, - c.getAlignmentY()); } - int absoluteAxis = X_AXIS; - - if (axis == LINE_AXIS) - absoluteAxis = tg.getComponentOrientation().isHorizontal() ? X_AXIS : Y_AXIS; - else if (axis == PAGE_AXIS) - absoluteAxis = tg.getComponentOrientation().isHorizontal() ? Y_AXIS : X_AXIS; - else - absoluteAxis = axis; - - if (absoluteAxis == X_AXIS) { - totalWidth = SizeRequirements.getTiledSizeRequirements(childWidth); - totalHeight = SizeRequirements.getAlignedSizeRequirements(childHeight); + // Compute the size requirement for the container + if (X_AXIS == getAbsoluteAxis(target)) { + totalWidth = SizeRequirements.getTiledSizeRequirements(childrenWidth); + totalHeight = SizeRequirements.getAlignedSizeRequirements(childrenHeight); } else { - totalWidth = SizeRequirements.getAlignedSizeRequirements(childWidth); - totalHeight = SizeRequirements.getTiledSizeRequirements(childHeight); + totalWidth = SizeRequirements.getAlignedSizeRequirements(childrenWidth); + totalHeight = SizeRequirements.getTiledSizeRequirements(childrenHeight); } } + /** + * Computes the absolute axis for this container. + * + * The absolute axis may depend on the component orientation. + * + * @param container + * @return + */ + protected final int getAbsoluteAxis(Container container) { + if (axis == LINE_AXIS) + return container.getComponentOrientation().isHorizontal() ? X_AXIS : Y_AXIS; + + if (axis == PAGE_AXIS) + return container.getComponentOrientation().isHorizontal() ? Y_AXIS : X_AXIS; + + return axis; + } + + /** + * Gets the dimension that represents this width and height plus the insets, but + * bound by the maximum integer value. + * + * @param insets + * @param width + * @param height + * @return + */ + protected final Dimension getBoundDimension(Insets insets, long width, long height) { + + long w = width + insets.left + insets.right; + long h = height + insets.top + insets.bottom; + + return new Dimension( + (int) Math.min(w, Integer.MAX_VALUE), + (int) Math.min(h, Integer.MAX_VALUE)); + } } Index: src/swingwtx/swing/ImageIcon.java =================================================================== --- src/swingwtx/swing/ImageIcon.java (revision 85) +++ src/swingwtx/swing/ImageIcon.java (working copy) @@ -12,14 +12,21 @@ package swingwtx.swing; -import swingwt.awt.*; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.URL; -import java.net.*; -import java.io.*; - import org.eclipse.swt.graphics.ImageData; +import swingwt.awt.Component; +import swingwt.awt.Graphics; +import swingwt.awt.Image; +import swingwt.awt.MediaTracker; +import swingwt.awt.image.ImageObserver; + public class ImageIcon implements Icon { private String description = null; @@ -164,4 +171,13 @@ return MediaTracker.COMPLETE; } + /** + * + * TODO Comment!! + * + * @return + */ + public ImageObserver getImageObserver() { + return null; + } } Index: src/swingwtx/swing/DefaultButtonModel.java =================================================================== --- src/swingwtx/swing/DefaultButtonModel.java (revision 0) +++ src/swingwtx/swing/DefaultButtonModel.java (revision 0) @@ -0,0 +1,263 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing; + +import swingwt.awt.event.ActionListener; +import swingwt.awt.event.ItemListener; +import swingwtx.swing.event.ChangeListener; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class DefaultButtonModel implements ButtonModel { + + /** + * TODO Comment!! + * + * @return + */ + //@Override + public Object[] getSelectedObjects() { + // TODO Auto-generated method stub + return null; + } + + /** + * TODO Comment!! + * + * @return + */ + //@Override + public boolean isArmed() { + // TODO Auto-generated method stub + return false; + } + + /** + * TODO Comment!! + * + * @return + */ + //@Override + public boolean isSelected() { + // TODO Auto-generated method stub + return false; + } + + /** + * TODO Comment!! + * + * @return + */ + //@Override + public boolean isEnabled() { + // TODO Auto-generated method stub + return false; + } + + /** + * TODO Comment!! + * + * @return + */ + //@Override + public boolean isPressed() { + // TODO Auto-generated method stub + return false; + } + + /** + * TODO Comment!! + * + * @return + */ + //@Override + public boolean isRollover() { + // TODO Auto-generated method stub + return false; + } + + /** + * TODO Comment!! + * + * @param b + */ + //@Override + public void setArmed(boolean b) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @param b + */ + //@Override + public void setSelected(boolean b) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @param b + */ + //@Override + public void setEnabled(boolean b) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @param b + */ + //@Override + public void setPressed(boolean b) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @param b + */ + //@Override + public void setRollover(boolean b) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @param key + */ + //@Override + public void setMnemonic(int key) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @return + */ + //@Override + public int getMnemonic() { + // TODO Auto-generated method stub + return 0; + } + + /** + * TODO Comment!! + * + * @param s + */ + //@Override + public void setActionCommand(String s) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @return + */ + //@Override + public String getActionCommand() { + // TODO Auto-generated method stub + return null; + } + + /** + * TODO Comment!! + * + * @param group + */ + //@Override + public void setGroup(ButtonGroup group) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @param l + */ + //@Override + public void addActionListener(ActionListener l) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @param l + */ + //@Override + public void removeActionListener(ActionListener l) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @param l + */ + //@Override + public void addItemListener(ItemListener l) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @param l + */ + //@Override + public void removeItemListener(ItemListener l) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @param l + */ + //@Override + public void addChangeListener(ChangeListener l) { + // TODO Auto-generated method stub + + } + + /** + * TODO Comment!! + * + * @param l + */ + //@Override + public void removeChangeListener(ChangeListener l) { + // TODO Auto-generated method stub + + } + +} Index: src/swingwtx/swing/text/JTextComponent.java =================================================================== --- src/swingwtx/swing/text/JTextComponent.java (revision 85) +++ src/swingwtx/swing/text/JTextComponent.java (working copy) @@ -301,6 +301,16 @@ return Color.white; } + /** + * + * TODO Comment!! + * + * @param b + */ + public void setDragEnabled(boolean b) { + + } + protected class TextEventHandler implements org.eclipse.swt.events.VerifyListener { public TextEventHandler() {} /* Index: src/swingwtx/swing/text/html/HTMLDocument.java =================================================================== --- src/swingwtx/swing/text/html/HTMLDocument.java (revision 0) +++ src/swingwtx/swing/text/html/HTMLDocument.java (revision 0) @@ -0,0 +1,28 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing.text.html; + + +import swingwtx.swing.text.DefaultStyledDocument; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class HTMLDocument extends DefaultStyledDocument { + + /** + * TODO Comment!! + */ + private static final long serialVersionUID = 1L; + + public void processHTMLFrameHyperlinkEvent(HTMLFrameHyperlinkEvent e) { + + } +} Index: src/swingwtx/swing/text/html/HTMLFrameHyperlinkEvent.java =================================================================== --- src/swingwtx/swing/text/html/HTMLFrameHyperlinkEvent.java (revision 0) +++ src/swingwtx/swing/text/html/HTMLFrameHyperlinkEvent.java (revision 0) @@ -0,0 +1,46 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing.text.html; + +import java.net.URL; + +import swingwtx.swing.event.HyperlinkEvent; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class HTMLFrameHyperlinkEvent extends HyperlinkEvent { + + /** + * TODO Comment!! + * + * @param source + * @param type + * @param u + */ + public HTMLFrameHyperlinkEvent(Object source, EventType type, URL u) { + super(source, type, u); + // TODO Auto-generated constructor stub + } + + /** + * + * TODO Comment!! + * + * @param source + * @param type + * @param u + * @param description + */ + public HTMLFrameHyperlinkEvent(Object source, EventType type, URL u, String description) { + super(source, type, u, description); + // TODO Auto-generated constructor stub + } +} Index: src/swingwtx/swing/JSplitPane.java =================================================================== --- src/swingwtx/swing/JSplitPane.java (revision 85) +++ src/swingwtx/swing/JSplitPane.java (working copy) @@ -141,7 +141,7 @@ public void setSwingWTParent(swingwt.awt.Container parent) throws Exception { descendantHasPeer = true; - ppeer = new SashForm(parent.getComposite(), SWT.BORDER); + ppeer = new SashForm(parent.getComposite(), SWT.NO_RADIO_GROUP | SWT.BORDER); peer = ppeer; composite = ppeer; this.parent = parent; Index: src/swingwtx/swing/DefaultRowSorter.java =================================================================== --- src/swingwtx/swing/DefaultRowSorter.java (revision 0) +++ src/swingwtx/swing/DefaultRowSorter.java (revision 0) @@ -0,0 +1,16 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class DefaultRowSorter extends RowSorter { +} Index: src/swingwtx/swing/JComponent.java =================================================================== --- src/swingwtx/swing/JComponent.java (revision 85) +++ src/swingwtx/swing/JComponent.java (working copy) @@ -12,24 +12,34 @@ package swingwtx.swing; -import swingwtx.swing.border.*; -import swingwtx.accessibility.*; -import swingwt.awt.*; -import swingwt.awt.event.*; +import java.beans.PropertyChangeListener; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Vector; -import swingwtx.swing.plaf.*; -import swingwtx.swing.event.*; +import swingwt.awt.Component; +import swingwt.awt.Container; +import swingwt.awt.Dimension; +import swingwt.awt.Graphics; +import swingwt.awt.Insets; +import swingwt.awt.Point; +import swingwt.awt.Rectangle; +import swingwt.awt.event.ActionListener; +import swingwt.awt.event.FocusEvent; +import swingwt.awt.event.FocusListener; +import swingwt.awt.event.MouseEvent; +import swingwt.awt.event.MouseListener; +import swingwtx.accessibility.AccessibleExtendedComponent; +import swingwtx.swing.border.Border; +import swingwtx.swing.event.AncestorListener; +import swingwtx.swing.plaf.ComponentUI; -import java.beans.*; -import java.util.*; - public class JComponent extends swingwt.awt.Container { /** The border for the component */ protected swingwtx.swing.border.Border border = null; - /** The component's accessible context */ - protected AccessibleContext accessibleContext = null; + /** Whether or not subclasses are supplying a peer in their setSwingWTParent() call - * if they don't, this component will supply a Composite peer (this is for Swing code * that descends JComopnent and paints on it) @@ -56,7 +66,6 @@ // The SwingWT's UI-component ( it does not do anything at this point ) protected ComponentUI componentUI = null; - /** Creates an empty JComponent which by default will use * a Composite peer (allowing you to paint on it). */ @@ -326,9 +335,6 @@ public void updateUI() {} - /** Calls invalidate */ - public void revalidate() { invalidate(); } - /** * Retrieves a property from the client, or null if * the key does not exist. @@ -361,14 +367,6 @@ getClientProperties().put(key, value); } - /** NOT IMPLEMENTED */ - public void setMargin(swingwt.awt.Insets i) {} - - /** Override in subclass to return something more specific */ - public AccessibleContext getAccessibleContext() { - return accessibleContext; - } - /** * Used to determine whether this component is a top level container * (overriden in subclasses), so validation code knows to work up @@ -402,15 +400,6 @@ return size; } - /** - * Overridden here - we still use the implementation in the superclass, but - * we are just checking if we are in a scrollpane container and set the - * preferred size on that if necessary. - */ - public void setPreferredSize(Dimension d) { - super.setPreferredSize(d); - } - /** Sets the InputMap for this component */ public final void setInputMap(int condition, InputMap inputMap) { if (condition == WHEN_FOCUSED) { focusInputMap = inputMap; } @@ -565,4 +554,41 @@ } return f; } + + /** + * + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ + protected class AccessibleJComponent extends AccessibleAWTContainer implements AccessibleExtendedComponent { + + public void addFocusListener(FocusListener l) { + // TODO Auto-generated method stub + } + } + + + // DEBUG SUPPORT + + /** + * Sub-types can override this to provide a better identifier during debug. + * + * @return + */ + public String debugId() { + String info = (null != border) ? border.debugId() + " / " : ""; + + if (null != layout) { + info += layout.getClass().getSimpleName(); + } + + String name = super.debugId(); + + if (info.length() > 0) { + return name + " [" + info + "]"; + } else { + return name; + } + } } Index: src/swingwtx/swing/SwingUtilities.java =================================================================== --- src/swingwtx/swing/SwingUtilities.java (revision 85) +++ src/swingwtx/swing/SwingUtilities.java (working copy) @@ -10,9 +10,15 @@ package swingwtx.swing; -import swingwt.awt.*; -import swingwtx.accessibility.*; +import org.eclipse.swt.widgets.Control; +import swingwt.awt.Component; +import swingwt.awt.Container; +import swingwt.awt.FontMetrics; +import swingwt.awt.Point; +import swingwt.awt.Window; +import swingwtx.accessibility.Accessible; + public abstract class SwingUtilities implements SwingConstants { public static void invokeAndWait(Runnable run) throws InterruptedException, java.lang.reflect.InvocationTargetException { @@ -70,29 +76,44 @@ * @author scott * */ - public static abstract class Task implements Runnable{ - Object retValue; + public static abstract class SwingWTRunnable implements Runnable { + /** + * The value to be returned. + */ + private Object retValue; + + /** + * Simply keeps the value returned by exec. + */ public void run(){ retValue = exec(); } + /** + * Implementations should return by this method the object + * they wish to be returned by sync(). + * + * @see SwingUtilities#sync(SwingWTRunnable) + * @return + */ public abstract Object exec(); } /** - * This method can be used so synchronized tasks can return - * objects. This makes it possible remove the temporary object fields - * that need to be used otherwise. Those fields are not thread safe. + * This method can be used so synchronized tasks can return objects. + * This makes it possible remove the temporary object fields that need + * to be used otherwise. Those fields are not thread safe. * - * @param task - * @return + * @param task a SwingWTRunnable object. + * @return the object returned by the task's exec() method. */ - public static Object invokeSyncReturn(Task task) { + public static Object sync(SwingWTRunnable task) { invokeSync(task); return task.retValue; } + public static int computeStringWidth(FontMetrics fontMetrics, String string) { if (string == null || string.length() == 0) { return 0; Index: src/swingwtx/swing/border/AbstractBorder.java =================================================================== --- src/swingwtx/swing/border/AbstractBorder.java (revision 85) +++ src/swingwtx/swing/border/AbstractBorder.java (working copy) @@ -15,21 +15,47 @@ public abstract class AbstractBorder implements Border { - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {} - public Insets getBorderInsets(Component c) { Insets insets = new Insets(); return getBorderInsets(c, insets); } - public Insets getBorderInsets(Component c, Insets insets) { return insets; } - public boolean isBorderOpaque() { return false; } - public Rectangle getInteriorRectangle(Component c, int x, int y, int width, int height) { - return getInteriorRectangle(c, this, x, y, width, height); - } - public static Rectangle getInteriorRectangle(Component c, Border b, int x, int y, int width, int height) { - Insets insets; - if(b != null) - insets = b.getBorderInsets(c); - else - insets = new Insets(0,0,0,0); - return new Rectangle( x+insets.left, y+insets.top, width-insets.right-insets.left, - height-insets.top-insets.bottom); - } - static boolean isLeftToRight( Component c ) { return c.getComponentOrientation().isLeftToRight(); } + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + } + + public Insets getBorderInsets(Component c) { + Insets insets = new Insets(); + return getBorderInsets(c, insets); + } + + public Insets getBorderInsets(Component c, Insets insets) { + return insets; + } + + public boolean isBorderOpaque() { + return false; + } + + public Rectangle getInteriorRectangle(Component c, int x, int y, int width, int height) { + return getInteriorRectangle(c, this, x, y, width, height); + } + + public static Rectangle getInteriorRectangle(Component c, Border b, int x, int y, int width, int height) { + Insets insets; + if (b != null) + insets = b.getBorderInsets(c); + else + insets = new Insets(0, 0, 0, 0); + return new Rectangle(x + insets.left, y + insets.top, width + - insets.right - insets.left, height - insets.top + - insets.bottom); + } + + static boolean isLeftToRight(Component c) { + return c.getComponentOrientation().isLeftToRight(); + } + + /** + * Sub-types can implement this to provide a better identifier during debug. + * + * @return + */ + public String debugId() { + return ""; + } } Index: src/swingwtx/swing/border/CompoundBorder.java =================================================================== --- src/swingwtx/swing/border/CompoundBorder.java (revision 85) +++ src/swingwtx/swing/border/CompoundBorder.java (working copy) @@ -55,4 +55,12 @@ } } + /** + * Sub-types can implement this to provide a better identifier during debug. + * + * @return + */ + public String debugId() { + return outside.debugId() + "/" + inside.debugId(); + } } Index: src/swingwtx/swing/border/TitledBorder.java =================================================================== --- src/swingwtx/swing/border/TitledBorder.java (revision 85) +++ src/swingwtx/swing/border/TitledBorder.java (working copy) @@ -111,7 +111,9 @@ this.border = border; } - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + // If you prefer this design, you may want to fix the getBorderInsets() method to add more + // space to the top + public void paintBorderOldDesign(Component c, Graphics g, int x, int y, int width, int height) { /** * This is a bit of a hack (and doesn't create perfect Swing-like behavior), * but IMO looks nicer than drawing a solid black line. If the SWT control happens to have @@ -139,14 +141,83 @@ g.drawString(title, 8, metrics.getHeight()/2 + 9); } + /** + * Size of the left, bottom and right parts of the border, in pixels. + */ + public static final int EXTERNAL_SIZE = 4; + + /** + * Padding between the outside of the border and the place were the line is drawn. + */ + public static final int EXTERNAL_PADDING = 3; + + /** + * Padding between the small top line and starting the title, as well as after the + * title and the continuation of the line. + */ + public static final int TITLE_PADDING = 2; + + /** + * How many pixels bellow the top line should the title be drawn. + */ + public static final int BELLOW_TOP_LINE = 4; + + + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + + /** + * This is a bit of a hack (and doesn't create perfect Swing-like behavior), + * but IMO looks nicer than drawing a solid black line. If the SWT control happens to have + * the SWT.BORDER style bit set (automatically done in JPanels if the border is an instance of + * TitledBorder), then don't draw the border. Instead, we just draw the title offset slighly. + */ + g.setColor( SystemColor.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW) ); + if (font != null) + g.setFont( font ); + FontMetrics metrics = c.getFontMetrics(g.getFont()); + + // Compute corners and paddings + int left_x = EXTERNAL_PADDING + x; + int right_x = width - EXTERNAL_PADDING + x; + int top_y = 2 * EXTERNAL_PADDING + y; + int bottom_y = height - EXTERNAL_PADDING + y; + + int smallTopLine = 5; + int titleWidth = title != null ? metrics.stringWidth(title) : 0; + + // top line, with some space for the title + g.drawLine(left_x, top_y, left_x + smallTopLine, top_y); + g.drawLine(left_x + smallTopLine + TITLE_PADDING + titleWidth + TITLE_PADDING, top_y, right_x, top_y); + + // left + g.drawLine(left_x, top_y, left_x, bottom_y); + + // bottom + g.drawLine(left_x, bottom_y, right_x, bottom_y); + + // right + g.drawLine(right_x, top_y, right_x, bottom_y); + + if (title != null) { + // The title goes in the selected (or default) color + if (color != null) + g.setColor( color ); + else + g.setColor(SystemColor.getSystemColor(SWT.COLOR_WIDGET_BORDER)); + + g.drawString(title, left_x + smallTopLine + TITLE_PADDING, top_y + BELLOW_TOP_LINE); + } + } + + public Insets getBorderInsets(Component c) { return getBorderInsets(c, new Insets()); } public Insets getBorderInsets(Component c, Insets insets) { - insets.top = insets.bottom = VERTICAL_INSET; - insets.top += insets.top / 2; - insets.left = insets.right = 4; + + insets.top = VERTICAL_INSET; + insets.left = insets.right = insets.bottom = EXTERNAL_SIZE; return insets; } @@ -180,4 +251,13 @@ public int getTitlePosition() { return titlePosition; } + + /** + * Sub-types can implement this to provide a better identifier during debug. + * + * @return + */ + public String debugId() { + return title; + } } Index: src/swingwtx/swing/border/SoftBevelBorder.java =================================================================== --- src/swingwtx/swing/border/SoftBevelBorder.java (revision 85) +++ src/swingwtx/swing/border/SoftBevelBorder.java (working copy) @@ -15,9 +15,18 @@ import swingwt.awt.*; public class SoftBevelBorder extends BevelBorder { - public SoftBevelBorder(int bevelType) { this.bevelType = bevelType; } - public SoftBevelBorder(int bevelType, Color highlight, Color shadow) { this(bevelType); } - public SoftBevelBorder(int bevelType, Color highlightOuterColor, - Color highlightInnerColor, Color shadowOuterColor, - Color shadowInnerColor) { this(bevelType); } + + public SoftBevelBorder(int bevelType) { + this.bevelType = bevelType; + } + + public SoftBevelBorder(int bevelType, Color highlight, Color shadow) { + this(bevelType); + } + + public SoftBevelBorder(int bevelType, Color highlightOuterColor, + Color highlightInnerColor, Color shadowOuterColor, + Color shadowInnerColor) { + this(bevelType); + } } Index: src/swingwtx/swing/border/EmptyBorder.java =================================================================== --- src/swingwtx/swing/border/EmptyBorder.java (revision 85) +++ src/swingwtx/swing/border/EmptyBorder.java (working copy) @@ -14,27 +14,78 @@ import swingwt.awt.*; +/** + * An empty border, but one that may occupy some space. + * + * @author Robin Rawson-Tetley + * @author Thiago Tonelli Bartolomei + */ public class EmptyBorder extends AbstractBorder implements Border { - protected int left, right, top, bottom; + + /** + * The paddings of the border. + */ + protected int left, right, top, bottom; - public EmptyBorder(Insets borderInsets) { - this(borderInsets.top, borderInsets.left, borderInsets.bottom, borderInsets.right); - } - public EmptyBorder(int top, int left, int bottom, int right) { - this.top = top; - this.left = left; - this.bottom = bottom; - this.right = right; - } + /** + * Creates a new empty border with paddings determined by these insets. + * + * @param borderInsets + */ + public EmptyBorder(Insets borderInsets) { + this(borderInsets.top, borderInsets.left, borderInsets.bottom, borderInsets.right); + } - public Insets getBorderInsets(Component c) { return getBorderInsets(); } - public Insets getBorderInsets() { return new Insets(top, left, bottom, right); } + /** + * Creates an empty border with these paddings. + * + * @param top + * @param left + * @param bottom + * @param right + */ + public EmptyBorder(int top, int left, int bottom, int right) { + this.top = top; + this.left = left; + this.bottom = bottom; + this.right = right; + } - public Insets getBorderInsets(Component c, Insets insets) { - insets.top = top; - insets.left = left; - insets.bottom = bottom; - insets.right = right; - return insets; - } + /** + * Gets the insets of this border. + * + * @param c + * @return + */ + public Insets getBorderInsets(Component c) { + return new Insets(top, left, bottom, right); + } + + /** + * Gets the insets of this border. + * + * @return + */ + public Insets getBorderInsets() { + return new Insets(top, left, bottom, right); + } + + /** + * Fills the insets with data from this border. + * + * @param c + * @param insets + * @return + */ + public Insets getBorderInsets(Component c, Insets insets) { + insets.top = top; + insets.left = left; + insets.bottom = bottom; + insets.right = right; + return insets; + } + + public String toString() { + return "[top=" + top + ",left=" + left + ",bottom=" + bottom + ",right=" + right + "]"; + } } Index: src/swingwtx/swing/border/Border.java =================================================================== --- src/swingwtx/swing/border/Border.java (revision 85) +++ src/swingwtx/swing/border/Border.java (working copy) @@ -11,8 +11,51 @@ package swingwtx.swing.border; +import swingwt.awt.Component; +import swingwt.awt.Graphics; +import swingwt.awt.Insets; + +/** + * An interface for widget border implementations. + * + * @author Robin Rawson-Tetley + */ public interface Border { - void paintBorder(swingwt.awt.Component c, swingwt.awt.Graphics g, int x, int y, int width, int height); - swingwt.awt.Insets getBorderInsets(swingwt.awt.Component c); - boolean isBorderOpaque(); + + /** + * Calls to give the border implementation a chance to paint itself on this component, + * using this Graphics. The coordinates indicate the position and size of the painted + * border. + * + * @param c + * @param g + * @param x + * @param y + * @param width + * @param height + */ + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height); + + /** + * Gets the border insets (its paddings). + * + * @param c the component in which the border is applied. + * @return + */ + public Insets getBorderInsets(Component c); + + /** + * True if the border is opaque, in which case it is responsible + * for painting its own background. + * + * @return + */ + public boolean isBorderOpaque(); + + /** + * Sub-types can implement this to provide a better identifier during debug. + * + * @return + */ + public String debugId(); } Index: src/swingwtx/swing/JSWTMenuComponent.java =================================================================== --- src/swingwtx/swing/JSWTMenuComponent.java (revision 85) +++ src/swingwtx/swing/JSWTMenuComponent.java (working copy) @@ -58,8 +58,8 @@ public int getMnemonic() { return (int) pMnemonic; }; - public void setMnemonic(char mnemonic) { pMnemonic = mnemonic; showMnemonic(); } - public void setMnemonic(int mnemonic) { pMnemonic = (char) mnemonic; showMnemonic(); } + public void setMnemonic(char mnemonic) { pMnemonic = mnemonic; setPeerText(); } + public void setMnemonic(int mnemonic) { pMnemonic = (char) mnemonic; setPeerText(); } /** @deprecated - Replaced by getText */ public String getLabel() { return getText(); } @@ -85,7 +85,7 @@ SwingUtilities.invokeSync(new Runnable() { public void run() { if (SwingWTUtils.isSWTMenuControlAvailable(peer)) { - peer.setText(pText); showMnemonic(); showAccelerator(); + peer.setText(pText); setPeerText(); showAccelerator(); } } }); @@ -97,7 +97,9 @@ public String getActionCommand() { return actionCommand; } public void setActionCommand(String command) { actionCommand = command; } - protected void showMnemonic() { + /* + * After changes to AbstractButton.setPeerText, this method seems unnecessary. + protected void setPeerText() { // If we don't have a mnemonic, don't show it if (pMnemonic == ' ') return; String text = ( peer == null ? pText : peer.getText()); @@ -115,6 +117,7 @@ setText(text); } } + */ private void showAccelerator() { // Already accelerator shown - don't do anything @@ -215,12 +218,12 @@ /** Add an ActionListener to this component */ public void addActionListener(ActionListener l) { - actionListeners.add(l); + this._getActionListeners().add(l); } /** Remove an ActionListener from the component */ public void removeActionListener(ActionListener l) { - actionListeners.remove(l); + this._getActionListeners().remove(l); } /** @@ -276,13 +279,13 @@ * properties were set in the meantime, this routine gets * called by JMenu/JMenuBar to set the cached properties. */ - public void setCachedProperties() { + public void assertCachedProperties() { final JSWTMenuComponent pthis = this; SwingUtilities.invokeSync(new Runnable() { public void run() { peer.setEnabled(pEnabled); if (pImage != null) peer.setImage(SwingWTUtils.getSWTImageFromSwingIcon(pthis, pImage)); - if (pMnemonic != ' ') showMnemonic(); + if (pMnemonic != ' ') setPeerText(); if (pAccelerator != 0) { peer.setAccelerator(pAccelerator); showAccelerator(); } peer.setText(pText); } Index: src/swingwtx/swing/JTable.java =================================================================== --- src/swingwtx/swing/JTable.java (revision 85) +++ src/swingwtx/swing/JTable.java (working copy) @@ -12,6 +12,7 @@ package swingwtx.swing; +import java.text.MessageFormat; import java.util.EventObject; import java.util.HashMap; import java.util.Vector; @@ -26,6 +27,7 @@ import swingwt.awt.Dimension; import swingwt.awt.Point; import swingwt.awt.event.MouseEvent; +import swingwt.awt.print.PrinterException; import swingwtx.swing.event.CellEditorListener; import swingwtx.swing.event.ChangeEvent; import swingwtx.swing.event.ListSelectionEvent; @@ -604,7 +606,7 @@ // Cached values and events ppeer.setLinesVisible(pLines); - setCachedProperties(); + assertCachedProperties(); registerEvents(); // Create a cursor and editor if there's some data and @@ -1143,4 +1145,45 @@ return editor; } + /** + * In Java 1.5 this is an enum of JTable. This implementation tries to preserve + * the behavior and the syntax used by clients, while being compatible to Java 1.4. + * + * @author Thiago Tonelli Bartolomei + */ + public static class PrintMode { + public static PrintMode NORMAL = new PrintMode(); + public static PrintMode FIT_WIDTH = new PrintMode(); + } + + /** + * + * TODO Comment!! + * + * @param printMode + * @param headerFormat + * @param footerFormat + * @return + * @throws PrinterException + */ + public boolean print(PrintMode printMode, + MessageFormat headerFormat, + MessageFormat footerFormat) throws PrinterException { + + return false; + } + + public void setRowSorter(RowSorter sorter) { + + } + + /** + * + * TODO Comment!! + * + * @param b + */ + public void setDragEnabled(boolean b) { + + } } Index: src/swingwtx/swing/BoundedRangeModel.java =================================================================== --- src/swingwtx/swing/BoundedRangeModel.java (revision 0) +++ src/swingwtx/swing/BoundedRangeModel.java (revision 0) @@ -0,0 +1,17 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public interface BoundedRangeModel { + +} Index: src/swingwtx/swing/JMenu.java =================================================================== --- src/swingwtx/swing/JMenu.java (revision 85) +++ src/swingwtx/swing/JMenu.java (working copy) @@ -48,7 +48,7 @@ if (SwingWTUtils.isSWTMenuControlAvailable(peer)) { try { c.setSwingWTParent(container, shell); - c.setCachedProperties(); + c.assertCachedProperties(); c.registerEvents(); } catch (Exception e) { Index: src/swingwtx/swing/JButton.java =================================================================== --- src/swingwtx/swing/JButton.java (revision 85) +++ src/swingwtx/swing/JButton.java (working copy) @@ -13,31 +13,52 @@ package swingwtx.swing; -import org.eclipse.swt.widgets.*; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.*; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.ToolItem; -import swingwt.awt.Color; +import swingwt.awt.Dimension; +import swingwt.awt.Insets; public class JButton extends AbstractButton implements SwingConstants, ButtonModel { - protected Icon pImage = null; protected boolean pDefaultCapable = true; protected swingwt.awt.Container pDefaultButtonParent = null; /** If this JButton is representing an SWT tool button, a reference to it */ protected ToolItem pSWTToolButton = null; + + public JButton() { + this("", null); + } + + public JButton(String text) { + this(text, null); + } + + public JButton(Action a) { + this(); + setAction(a); + } + + public JButton(Icon icon) { + this("", icon); + } + + public JButton(String text, Icon icon) { + super(); + pHAlign = CENTER; + setText(text); + setIcon(icon); + } + + /** + * @see AbstractButton#setAction(Action, boolean) + */ + protected JButton(Action a, boolean addAsListener) { + setAction(a, addAsListener); + } - public JButton() {this(""); } - public JButton(String text) { pText = text; setModel(this); showMnemonic(); pHAlign = CENTER; } - public JButton(Action a) { setAction(a); pHAlign = CENTER; } - public JButton(Icon icon) { pImage = icon; pHAlign = CENTER; } - public JButton(String text, Icon icon) { pImage = icon; pText = text; pHAlign = CENTER; setModel(this); showMnemonic(); } - - /** @see AbstractButton.setAction(Action, bool) */ - protected JButton(Action a, boolean addAsListener) { setAction(a, addAsListener); } - /** * If this JButton is part of a JButtonMappedAction, update it */ @@ -57,8 +78,8 @@ */ private void updateToolButton() { if (pSWTToolButton == null) { - return; - } + return; + } SwingUtilities.invokeSync(new Runnable() { public void run() { pSWTToolButton.setText(getText()); @@ -69,21 +90,13 @@ }); } - public Icon getIcon() { return pImage; } - - public void setIcon(Icon icon) { - pImage = icon; - final JButton pthis = this; - SwingUtilities.invokeSync(new Runnable() { - public void run() { - if (SwingWTUtils.isSWTControlAvailable(ppeer)) ppeer.setImage(SwingWTUtils.getSWTImageFromSwingIcon(pthis, pImage)); - // renderText(); -- No longer needed - updateToolButton(); - updateMappedAction(); - } - }); - } - + public void setIcon(Icon icon) { + super.setIcon(icon); + // renderText(); -- No longer needed + updateToolButton(); + updateMappedAction(); + } + /** Overrides superclass so we can update any ToolItem */ public void setToolTipText(String text) { super.setToolTipText(text); @@ -243,20 +256,50 @@ ================================== */ - - /** Overriden to calculate non-realised - * preferred size. - */ + /** + * Overridden to calculate non-realized preferred size. + *//* protected swingwt.awt.Dimension calculatePreferredSize() { - // Use the text height/width + 6 pixels for width - // 10 for height button borders. - swingwt.awt.Dimension size = new swingwt.awt.Dimension( - SwingWTUtils.getRenderStringWidth(pText) + 6, - SwingWTUtils.getRenderStringHeight(pText) + 12); + + Dimension size = + (null != pIcon) ? + // if there's an icon, use the icon's size + new Dimension(pIcon.getIconWidth(), pIcon.getIconHeight()) : + + // Use the text height/width + 6 pixels for width + // 10 for height button borders. + new Dimension( + SwingWTUtils.getRenderStringWidth(pText) + 34, + SwingWTUtils.getRenderStringHeight(pText) + 10); + + Insets i = this.getMargin(); + if (null != i) { + size.height += i.top + i.bottom; + size.width += i.left + i.right; + } setSize(size); return size; } + protected Dimension computePreferredSize() { + if (null != pIcon) + return calculatePreferredSize(); + + return super.computePreferredSize(); + }*/ + + /** + * JButtons that have HTML in the text have an unlimited maximum width. + * + * @return + */ + public Dimension getMaximumSize() { + Dimension d = super.getMaximumSize(); + if (containsHTML) + return new Dimension(Integer.MAX_VALUE, d.height); + return d; + } + protected int getSWTFlags() { return (parent instanceof JToolBar ? SWT.FLAT : SWT.PUSH); } @@ -274,15 +317,15 @@ peer = ppeer; // Refresh foreground color, if set - if (pForeground != null) setForeground(pForeground); + if (pForeground != null) + setForeground(pForeground); - if (pText != null) - ppeer.setText(pText); + if (pFont != null) + ppeer.setFont(pFont.getSWTFont()); - if (pMnemonic != ' ') showMnemonic(); - if (pImage != null) ppeer.setImage(SwingWTUtils.getSWTImageFromSwingIcon(this, pImage)); - if (pFont != null) ppeer.setFont(pFont.getSWTFont()); - ppeer.setAlignment(SwingWTUtils.translateSwingAlignmentConstant(pVAlign) | + // @see AbstractButton#setVerticalAlignment(int) + ppeer.setAlignment( + // SwingWTUtils.translateSwingAlignmentConstant(pVAlign) | SwingWTUtils.translateSwingAlignmentConstant(pHAlign)); // renderText(); -- RRT 9 Aug 06 - No longer needed for SWT 3.2 @@ -311,45 +354,7 @@ pDefaultButtonParent = window; } - // TODO: This doesn't mesh with ButtonModels and ButtonGroups. - // Use ButtonGroup.setSelected() to workaround, for now. (Can't here because the JButton - // is by default it's own ButtonModel, so we'd end up in an infinite loop. - public boolean isSelected() { return false; } - public void setSelected(boolean b) {} - - public void addItemListener(swingwt.awt.event.ItemListener l) { - } - - public Object[] getSelectedObjects() { - return null; - } - - public void removeItemListener(swingwt.awt.event.ItemListener l) { - } - - public boolean isArmed() { - return false; - } - - public boolean isPressed() { - return false; - } - - public boolean isRollover() { - return false; - } - - public void setArmed(boolean b) { - } - - public void setPressed(boolean b) { - } - - public void setRollover(boolean b) { - } - public boolean isDefaultCapable() { - return true; + return true; } - } Index: src/swingwtx/swing/Box.java =================================================================== --- src/swingwtx/swing/Box.java (revision 85) +++ src/swingwtx/swing/Box.java (working copy) @@ -12,7 +12,9 @@ package swingwtx.swing; -import swingwt.awt.*; +import swingwt.awt.Component; +import swingwt.awt.Container; +import swingwt.awt.Dimension; /** * @author Submitted by a kind developer who remains anonymous @@ -84,7 +86,16 @@ // to date because BoxLayout alignment breaks. return new Filler(new Dimension(0,0), new Dimension(0,0), new Dimension(0, Short.MAX_VALUE)); } - + + /** + * Sub-types can override this to provide a better identifier during debug. + * + * @return + */ + public String debugId() { + return "Box"; + } + public static class Filler extends JPanel { public Filler(Dimension min, Dimension pref, Dimension max) { Index: src/swingwtx/swing/JLabel.java =================================================================== --- src/swingwtx/swing/JLabel.java (revision 85) +++ src/swingwtx/swing/JLabel.java (working copy) @@ -299,6 +299,12 @@ public void run() { ppeer.setImage(SwingWTUtils.getSWTImageFromSwingIcon(this, icon)); + // Get the background of a parent that has it set + Container c = this; + while(c != null && ! c.isBackgroundSet()) + c = c.getParent(); + if (null != c) + this.setBackground(c.getBackground()); } public void setIcon(Icon icon) { @@ -322,4 +328,15 @@ this.parent = parent; } } + + // DEBUG SUPPORT + + /** + * Sub-types can override this to provide a better identifier during debug. + * + * @return + */ + public String debugId() { + return "JLabel [\"" + this.getText() + "\"]"; + } } Index: src/swingwtx/swing/JSlider.java =================================================================== --- src/swingwtx/swing/JSlider.java (revision 85) +++ src/swingwtx/swing/JSlider.java (working copy) @@ -12,14 +12,19 @@ package swingwtx.swing; -import swingwtx.swing.event.*; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Vector; -import org.eclipse.swt.widgets.*; import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Scale; -import java.util.*; +import swingwtx.accessibility.Accessible; +import swingwtx.swing.event.ChangeEvent; +import swingwtx.swing.event.ChangeListener; -public class JSlider extends JComponent implements SwingConstants { + +public class JSlider extends JComponent implements SwingConstants, Accessible { protected int orientation = SwingConstants.HORIZONTAL; protected int min = 0; @@ -44,6 +49,15 @@ this.value = value; } + /** + * + * TODO Comment!! + * + * @param brm + */ + public JSlider(BoundedRangeModel brm) { + + } public void setMinimum(final int minimum){ this.min=minimum; if (SwingWTUtils.isSWTControlAvailable(ppeer)) Index: src/swingwtx/swing/plaf/basic/BasicBorders.java =================================================================== --- src/swingwtx/swing/plaf/basic/BasicBorders.java (revision 0) +++ src/swingwtx/swing/plaf/basic/BasicBorders.java (revision 0) @@ -0,0 +1,23 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing.plaf.basic; + +import swingwtx.swing.border.AbstractBorder; +import swingwtx.swing.plaf.UIResource; + + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class BasicBorders { + + public static class MarginBorder extends AbstractBorder implements UIResource { + } +} Index: src/swingwtx/swing/plaf/metal/OceanTheme.java =================================================================== --- src/swingwtx/swing/plaf/metal/OceanTheme.java (revision 0) +++ src/swingwtx/swing/plaf/metal/OceanTheme.java (revision 0) @@ -0,0 +1,18 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing.plaf.metal; + + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class OceanTheme extends DefaultMetalTheme { + +} Index: src/swingwtx/swing/plaf/BorderUIResource.java =================================================================== --- src/swingwtx/swing/plaf/BorderUIResource.java (revision 0) +++ src/swingwtx/swing/plaf/BorderUIResource.java (revision 0) @@ -0,0 +1,76 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing.plaf; + +import java.io.Serializable; + +import swingwt.awt.Component; +import swingwt.awt.Graphics; +import swingwt.awt.Insets; +import swingwtx.swing.border.Border; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class BorderUIResource implements Border, UIResource, Serializable { + + /** + * TODO Comment!! + */ + private static final long serialVersionUID = 1L; + + public BorderUIResource(Border delegate) { + + } + + /** + * TODO Comment!! + * + * @param c + * @param g + * @param x + * @param y + * @param width + * @param height + */ + public void paintBorder(Component c, Graphics g, int x, int y, int width,int height) { + // TODO Auto-generated method stub + } + + /** + * TODO Comment!! + * + * @param c + * @return + */ + public Insets getBorderInsets(Component c) { + // TODO Auto-generated method stub + return null; + } + + /** + * TODO Comment!! + * + * @return + */ + public boolean isBorderOpaque() { + // TODO Auto-generated method stub + return false; + } + + /** + * Sub-types can implement this to provide a better identifier during debug. + * + * @return + */ + public String debugId() { + return ""; + } +} Index: src/swingwtx/swing/JFrame.java =================================================================== --- src/swingwtx/swing/JFrame.java (revision 85) +++ src/swingwtx/swing/JFrame.java (working copy) @@ -13,8 +13,12 @@ package swingwtx.swing; -import swingwt.awt.*; +import org.eclipse.swt.widgets.Shell; +import swingwt.awt.Component; +import swingwt.awt.Container; +import swingwt.awt.GraphicsConfiguration; + public class JFrame extends swingwt.awt.Frame implements WindowConstants, RootPaneContainer { @@ -26,8 +30,8 @@ public JFrame(String title) {super(title); } public JFrame(GraphicsConfiguration gc) { super(gc); } - public void setCachedProperties() { - super.setCachedProperties(); + public void assertCachedProperties() { + super.assertCachedProperties(); setExtendedState(state); } /** Handy for layout problems. Toggles the window between @@ -37,14 +41,15 @@ public void toggleWindowState() { SwingUtilities.invokeSync(new Runnable() { public void run() { + Shell shell = (Shell) peer; if (isMax) { - peer.setMaximized(false); - peer.setMaximized(true); + shell.setMaximized(false); + shell.setMaximized(true); } else { - peer.setMaximized(true); - peer.setMaximized(false); + shell.setMaximized(true); + shell.setMaximized(false); } } }); Index: src/swingwtx/swing/RowSorter.java =================================================================== --- src/swingwtx/swing/RowSorter.java (revision 0) +++ src/swingwtx/swing/RowSorter.java (revision 0) @@ -0,0 +1,17 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public abstract class RowSorter { + +} Index: src/swingwtx/swing/JPanel.java =================================================================== --- src/swingwtx/swing/JPanel.java (revision 85) +++ src/swingwtx/swing/JPanel.java (working copy) @@ -16,60 +16,80 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; -import swingwt.awt.Color; +import swingwt.awt.Dimension; import swingwt.awt.Graphics; import swingwt.awt.Insets; public class JPanel extends JComponent { - /** The panel's peer */ - protected Composite ppeer = null; - protected boolean opaque = true; + /** The panel's peer */ + protected Composite ppeer = null; - /** Creates a new JPanel */ - public JPanel() {this(false);} - /** Creates a new JPanel with the specified buffering scheme - * @param isDoubleBuffered Whether or not to double buffer paint callbacks - */ - public JPanel(boolean isDoubleBuffered) { this(new swingwt.awt.FlowLayout(), false); } - /** Creates a new JPanel with the specified layout - * @param layout The layout manager to use - */ - public JPanel(swingwt.awt.LayoutManager layout) { - setLayout(layout); - } + protected boolean opaque = true; - /** Creates a new JPanel with the specified layout and buffering scheme - * @param layout The layout manager to use - * @param isDoubleBuffered Whether or not to double buffer paint callbacks - */ - public JPanel(swingwt.awt.LayoutManager layout, boolean isDoubleBuffered) { - setLayout(layout); - } - /** Creates a new JPanel with the specified layout - * @param layout The layout manager to use - */ - public JPanel(swingwt.awt.LayoutManager2 layout) { - setLayout(layout); - } - - /** Creates a new JPanel with the specified layout and buffering scheme - * @param layout The layout manager to use - * @param isDoubleBuffered Whether or not to double buffer paint callbacks - */ - public JPanel(swingwt.awt.LayoutManager2 layout, boolean isDoubleBuffered) { - setLayout(layout); - } + /** + * Creates a new JPanel. + */ + public JPanel() { + this(false); + } - /** Overriden to calculate non-realised - * preferred size. - */ - protected swingwt.awt.Dimension calculatePreferredSize() { - // Default 300x200 - swingwt.awt.Dimension size = new swingwt.awt.Dimension(300, 200); - setSize(size); - return size; - } + /** + * Creates a new JPanel with the specified buffering scheme + * + * @param isDoubleBuffered Whether or not to double buffer paint callbacks + */ + public JPanel(boolean isDoubleBuffered) { + this(new swingwt.awt.FlowLayout(), false); + } + + /** + * Creates a new JPanel with the specified layout + * + * @param layout The layout manager to use + */ + public JPanel(swingwt.awt.LayoutManager layout) { + setLayout(layout); + } + + /** + * Creates a new JPanel with the specified layout and buffering scheme + * + * @param layout The layout manager to use + * @param isDoubleBuffered Whether or not to double buffer paint callbacks + */ + public JPanel(swingwt.awt.LayoutManager layout, boolean isDoubleBuffered) { + setLayout(layout); + } + + /** + * Creates a new JPanel with the specified layout + * + * @param layout The layout manager to use + */ + public JPanel(swingwt.awt.LayoutManager2 layout) { + setLayout(layout); + } + + /** + * Creates a new JPanel with the specified layout and buffering scheme + * + * @param layout The layout manager to use + * @param isDoubleBuffered Whether or not to double buffer paint callbacks + */ + public JPanel(swingwt.awt.LayoutManager2 layout, boolean isDoubleBuffered) { + setLayout(layout); + } + + /** + * Overriden to calculate non-realised preferred size. + */ + protected swingwt.awt.Dimension calculatePreferredSize() { + // Default 300x200 + swingwt.awt.Dimension size = new swingwt.awt.Dimension(300, 200); + setSize(size); + return size; + } private boolean usePlatformBorder() { boolean usePlatformBorder = @@ -98,7 +118,7 @@ public void setSwingWTParent(swingwt.awt.Container parent) throws Exception { descendantHasPeer = true; - ppeer = new Composite(parent.getComposite(), usePlatformBorder() ? SWT.BORDER : SWT.NONE ); + ppeer = new Composite(parent.getComposite(), SWT.NO_RADIO_GROUP | (usePlatformBorder() ? SWT.BORDER : SWT.NONE) ); peer = ppeer; composite = ppeer; this.parent = parent; @@ -118,13 +138,4 @@ else return super.getSize(); } - /** Returns the width of the peer - * @return the width - */ - public int getWidth() { return getSize().width; } - /** Returns the height of the peer - * @return the height - */ - public int getHeight() { return getSize().height; } - } Index: src/swingwtx/swing/JFileChooser.java =================================================================== --- src/swingwtx/swing/JFileChooser.java (revision 85) +++ src/swingwtx/swing/JFileChooser.java (working copy) @@ -12,17 +12,30 @@ package swingwtx.swing; -import swingwt.awt.*; -import swingwt.awt.event.*; -import swingwtx.swing.border.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.util.Vector; -import org.eclipse.swt.*; +import org.eclipse.swt.SWT; -import java.beans.*; -import java.io.*; -import java.util.*; +import swingwt.awt.BorderLayout; +import swingwt.awt.Component; +import swingwt.awt.Dimension; +import swingwt.awt.FlowLayout; +import swingwt.awt.Frame; +import swingwt.awt.GridLayout; +import swingwt.awt.event.ActionEvent; +import swingwt.awt.event.ActionListener; +import swingwt.awt.event.ItemEvent; +import swingwt.awt.event.ItemListener; +import swingwt.awt.event.MouseAdapter; +import swingwt.awt.event.MouseEvent; +import swingwtx.swing.border.EmptyBorder; +import swingwtx.swing.filechooser.FileView; + /** * JFileChooser is now a custom control (like Swing's), however * if you only use the showXDialog() methods without calling @@ -582,6 +595,26 @@ return dialogReturnValue; } + /** + * + * TODO Comment!! + * + * @param b + */ + public void setDragEnabled(boolean b) { + + } + + /** + * + * TODO Comment!! + * + * @param fileView + */ + public void setFileView(FileView fileView) { + + } + public String getTitle() { return dialogTitle; } public void setTitle(String title) { dialogTitle = title; } Index: src/swingwtx/swing/JSeparator.java =================================================================== --- src/swingwtx/swing/JSeparator.java (revision 85) +++ src/swingwtx/swing/JSeparator.java (working copy) @@ -58,9 +58,9 @@ } } - public void setCachedProperties() { + public void assertCachedProperties() { if(peer != null) { - super.setCachedProperties(); + super.assertCachedProperties(); } } public void dispose() { Index: src/swingwtx/swing/ButtonGroup.java =================================================================== --- src/swingwtx/swing/ButtonGroup.java (revision 85) +++ src/swingwtx/swing/ButtonGroup.java (working copy) @@ -10,7 +10,8 @@ */ package swingwtx.swing; -import java.util.*; +import java.util.Enumeration; +import java.util.Vector; /** * This class is used to create a multiple-exclusion scope for @@ -24,63 +25,113 @@ */ public class ButtonGroup { + /** + * The buttons that participate in this group. + */ protected Vector buttons = new Vector(); - ButtonModel selection = null; - public ButtonGroup() {} + /** + * The model of the selected button. + */ + protected ButtonModel selectedModel = null; + /** + * Creates an empty group. + */ + public ButtonGroup() { + } + + /** + * Adds this button to the group. + * + * @param b the button to be added. + */ public void add(AbstractButton b) { + if (null == b) + return; + buttons.add(b); - if (b.isSelected()) { - if (selection == null) { - selection = b.getModel(); - } else { - b.setSelected(false); - } - } + + if (b.isSelected()) + if (null == selectedModel) + selectedModel = b.getModel(); + else + b._setSelected(false); + b.getModel().setGroup(this); } + /** + * Removes this button from the group. + * + * @param b + */ public void remove(AbstractButton b) { - if(b == null) { - return; - } + if (null == b) + return; + buttons.remove(b); - if(b.getModel() == selection) { - selection = null; - } + + if(b.getModel() == selectedModel) + selectedModel = null; + b.getModel().setGroup(null); } + /** + * Gets an enumeration with all buttons in this group. + * + * @return + */ public Enumeration getElements() { return buttons.elements(); } + /** + * Gets the selection model of the selected button. + * + * @return + */ public ButtonModel getSelection() { - return selection; + return selectedModel; } - public void setSelected(ButtonModel m, boolean b) { - if (b && m != null && m != selection) { - ButtonModel oldSelection = selection; - selection = m; - if (oldSelection != null) { + /** + * If selectThisButton is true, then select this model. + * + * @param newModel + * @param selectThisButton + */ + public void setSelected(ButtonModel newModel, boolean selectThisButton) { + if (selectThisButton && null != newModel && selectedModel != newModel) { + + ButtonModel oldSelection = selectedModel; + selectedModel = newModel; + + if (null != oldSelection) oldSelection.setSelected(false); - } - m.setSelected(true); + + newModel.setSelected(true); } } + /** + * Checks whether this is the selected button model, + * according to this group. + * + * @param m + * @return + */ public boolean isSelected(ButtonModel m) { - return (m == selection); + return (selectedModel == m); } + /** + * The number of buttons in the group. + * + * @return + */ public int getButtonCount() { - if (buttons == null) { - return 0; - } else { - return buttons.size(); - } + return buttons.size(); } - } Index: src/swingwtx/custom/JSWTTable.java =================================================================== --- src/swingwtx/custom/JSWTTable.java (revision 85) +++ src/swingwtx/custom/JSWTTable.java (working copy) @@ -1120,7 +1120,7 @@ // Cached values and events ppeer.setLinesVisible(pLines); - setCachedProperties(); + assertCachedProperties(); registerEvents(); viewer.refresh(); Index: src/swingwtx/custom/JClosableTabbedPane.java =================================================================== --- src/swingwtx/custom/JClosableTabbedPane.java (revision 85) +++ src/swingwtx/custom/JClosableTabbedPane.java (working copy) @@ -308,7 +308,7 @@ public void setSwingWTParent(swingwt.awt.Container parent) throws Exception { descendantHasPeer = true; - ppeer = new CTabFolderSwingWT(parent.getComposite(), SwingWTUtils.translateSwingAlignmentConstant(pTabPlacement)); + ppeer = new CTabFolderSwingWT(parent.getComposite(), SWT.NO_RADIO_GROUP | SwingWTUtils.translateSwingAlignmentConstant(pTabPlacement)); peer = ppeer; composite = ppeer; this.parent = parent; Index: src/swingwtx/custom/JCoolBar.java =================================================================== --- src/swingwtx/custom/JCoolBar.java (revision 85) +++ src/swingwtx/custom/JCoolBar.java (working copy) @@ -85,7 +85,7 @@ public void setSwingWTParent(swingwt.awt.Container parent) throws Exception { descendantHasPeer = true; - ppeer = new CoolBar(parent.getComposite(), SWT.BORDER); + ppeer = new CoolBar(parent.getComposite(), SWT.NO_RADIO_GROUP | SWT.BORDER); peer = ppeer; composite = ppeer; this.parent = parent; Index: src15/swingwtx/swing/RowSorter.java =================================================================== --- src15/swingwtx/swing/RowSorter.java (revision 0) +++ src15/swingwtx/swing/RowSorter.java (revision 0) @@ -0,0 +1,17 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public abstract class RowSorter { + +} Index: src15/swingwtx/swing/table/TableRowSorter.java =================================================================== --- src15/swingwtx/swing/table/TableRowSorter.java (revision 0) +++ src15/swingwtx/swing/table/TableRowSorter.java (revision 0) @@ -0,0 +1,23 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing.table; + +import swingwtx.swing.DefaultRowSorter; + + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class TableRowSorter extends DefaultRowSorter { + + public TableRowSorter(M model) { + + } +} Index: src15/swingwtx/swing/DefaultRowSorter.java =================================================================== --- src15/swingwtx/swing/DefaultRowSorter.java (revision 0) +++ src15/swingwtx/swing/DefaultRowSorter.java (revision 0) @@ -0,0 +1,17 @@ +/** + * SwingWT + * + * This program is dual licenced under the terms of the Common Public + * License v1.0 and the GNU Lesser Public License (LGPL) version 2 or + * later. Please choose whichever is most applicable to you. + */ +package swingwtx.swing; + +/** + * TODO Comment!! + * + * @author Thiago Tonelli Bartolomei + */ +public class DefaultRowSorter extends RowSorter { + +}