You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(97) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(127) |
Feb
(34) |
Mar
(16) |
Apr
(26) |
May
(55) |
Jun
(107) |
Jul
(36) |
Aug
(72) |
Sep
(90) |
Oct
(41) |
Nov
(27) |
Dec
(13) |
2008 |
Jan
(37) |
Feb
(39) |
Mar
(98) |
Apr
(115) |
May
(134) |
Jun
(120) |
Jul
(86) |
Aug
(149) |
Sep
(68) |
Oct
(66) |
Nov
(104) |
Dec
(49) |
2009 |
Jan
(131) |
Feb
(132) |
Mar
(125) |
Apr
(172) |
May
(161) |
Jun
(43) |
Jul
(47) |
Aug
(38) |
Sep
(18) |
Oct
(6) |
Nov
(1) |
Dec
(15) |
2010 |
Jan
(21) |
Feb
(8) |
Mar
(10) |
Apr
(4) |
May
(9) |
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
(2) |
Nov
|
Dec
(4) |
2011 |
Jan
(23) |
Feb
(10) |
Mar
(13) |
Apr
(3) |
May
|
Jun
(19) |
Jul
(11) |
Aug
(22) |
Sep
|
Oct
(4) |
Nov
(2) |
Dec
(12) |
2012 |
Jan
(3) |
Feb
(4) |
Mar
(7) |
Apr
(3) |
May
|
Jun
(1) |
Jul
(1) |
Aug
(30) |
Sep
(3) |
Oct
(2) |
Nov
|
Dec
(8) |
2013 |
Jan
(3) |
Feb
(40) |
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(12) |
Dec
|
2021 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
From: <fd...@us...> - 2007-02-11 22:25:22
|
Revision: 3119 http://jnode.svn.sourceforge.net/jnode/?rev=3119&view=rev Author: fduminy Date: 2007-02-11 14:25:20 -0800 (Sun, 11 Feb 2007) Log Message: ----------- fixed bug in splitInColumns method Modified Paths: -------------- trunk/shell/src/shell/org/jnode/shell/Line.java Modified: trunk/shell/src/shell/org/jnode/shell/Line.java =================================================================== --- trunk/shell/src/shell/org/jnode/shell/Line.java 2007-02-11 22:23:44 UTC (rev 3118) +++ trunk/shell/src/shell/org/jnode/shell/Line.java 2007-02-11 22:25:20 UTC (rev 3119) @@ -213,7 +213,7 @@ } } - final int columnWidth = maxWidth + separatorWidth; + final int columnWidth = Math.min(SCREEN_WIDTH, maxWidth + separatorWidth); final int nbColumns = SCREEN_WIDTH / columnWidth; final boolean lastLineIsFull = ((items.length % nbColumns) == 0); final int nbLines = (items.length / nbColumns) + (lastLineIsFull ? 0 : 1); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fd...@us...> - 2007-02-11 22:23:45
|
Revision: 3118 http://jnode.svn.sourceforge.net/jnode/?rev=3118&view=rev Author: fduminy Date: 2007-02-11 14:23:44 -0800 (Sun, 11 Feb 2007) Log Message: ----------- removed "ugly workaround" :-) that is no more needed since we went to generics Modified Paths: -------------- trunk/shell/src/shell/org/jnode/shell/help/Argument.java Modified: trunk/shell/src/shell/org/jnode/shell/help/Argument.java =================================================================== --- trunk/shell/src/shell/org/jnode/shell/help/Argument.java 2007-02-11 22:19:06 UTC (rev 3117) +++ trunk/shell/src/shell/org/jnode/shell/help/Argument.java 2007-02-11 22:23:44 UTC (rev 3118) @@ -76,11 +76,7 @@ if (list.size() == 1) return (String) list.iterator().next() + " "; // list matching - String[] result = (String[]) list - .toArray(new String[ list.size()/* - * TODO remove this ugly - * workaround - */]); + String[] result = list.toArray(new String[list.size()]); list(result); // return the common part, i.e. complete as much as possible This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fd...@us...> - 2007-02-11 22:19:11
|
Revision: 3117 http://jnode.svn.sourceforge.net/jnode/?rev=3117&view=rev Author: fduminy Date: 2007-02-11 14:19:06 -0800 (Sun, 11 Feb 2007) Log Message: ----------- - IBMPartitionTypes is now an enum instead of an interface - added some functions for disk partitionning - extracted partionning functions from FDiskCommand to put them in the class PartitionHelper Modified Paths: -------------- trunk/fs/build.xml trunk/fs/descriptors/org.jnode.partitions.command.xml trunk/fs/src/driver/org/jnode/driver/block/PartitionableBlockAlignmentSupport.java trunk/fs/src/driver/org/jnode/driver/block/PartitionableBlockDeviceAPI.java trunk/fs/src/driver/org/jnode/driver/block/ide/disk/IDEDiskDriver.java trunk/fs/src/driver/org/jnode/driver/bus/ide/IDEDeviceAPI.java trunk/fs/src/fs/org/jnode/fs/fat/BootSector.java trunk/fs/src/fs/org/jnode/fs/fat/FatFileSystemType.java trunk/fs/src/fs/org/jnode/fs/jfat/FatFileSystemType.java trunk/fs/src/fs/org/jnode/fs/ntfs/NTFSFileSystemType.java trunk/fs/src/fs/org/jnode/partitions/PartitionTable.java trunk/fs/src/fs/org/jnode/partitions/command/FdiskCommand.java trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTable.java trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTableEntry.java trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTypes.java trunk/fs/src/test/org/jnode/test/fs/filesystem/AbstractFSTest.java trunk/fs/src/test/org/jnode/test/fs/filesystem/FSConfigurations.java trunk/fs/src/test/org/jnode/test/fs/filesystem/FSContext.java trunk/fs/src/test/org/jnode/test/fs/filesystem/FSTestSuite.java trunk/fs/src/test/org/jnode/test/fs/filesystem/config/DeviceParam.java trunk/fs/src/test/org/jnode/test/fs/filesystem/config/FileParam.java trunk/fs/src/test/org/jnode/test/fs/filesystem/config/JNodeDeviceParam.java trunk/fs/src/test/org/jnode/test/fs/filesystem/config/ResourceParam.java Modified: trunk/fs/build.xml =================================================================== --- trunk/fs/build.xml 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/build.xml 2007-02-11 22:19:06 UTC (rev 3117) @@ -63,6 +63,16 @@ <target name="clean"> <jnode.clean/> </target> + +<!-- tests FileSystems --> + <target name="tests" depends="compile" description="Run FS tests with JUnit"> + <junit fork="yes" haltonerror="false" haltonfailure="false" printsummary="on" includeantruntime="true"> + <classpath refid="cp-jnode" /> + + <formatter type="plain" usefile="false" /> + <test name="org.jnode.test.fs.AllFSTest" /> + </junit> + </target> </project> Modified: trunk/fs/descriptors/org.jnode.partitions.command.xml =================================================================== --- trunk/fs/descriptors/org.jnode.partitions.command.xml 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/descriptors/org.jnode.partitions.command.xml 2007-02-11 22:19:06 UTC (rev 3117) @@ -17,6 +17,7 @@ <runtime> <library name="jnode-fs.jar"> <export name="org.jnode.partitions.command.*"/> + <export name="org.jnode.partitions.help.argument.*"/> </library> </runtime> Modified: trunk/fs/src/driver/org/jnode/driver/block/PartitionableBlockAlignmentSupport.java =================================================================== --- trunk/fs/src/driver/org/jnode/driver/block/PartitionableBlockAlignmentSupport.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/driver/org/jnode/driver/block/PartitionableBlockAlignmentSupport.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -24,20 +24,22 @@ import java.io.IOException; import org.jnode.partitions.PartitionTable; +import org.jnode.partitions.PartitionTableEntry; /** * @author Ewout Prangsma (ep...@us...) */ -public class PartitionableBlockAlignmentSupport extends BlockAlignmentSupport - implements PartitionableBlockDeviceAPI { +public class PartitionableBlockAlignmentSupport <PTE extends PartitionTableEntry> + extends BlockAlignmentSupport + implements PartitionableBlockDeviceAPI<PTE> { - private final PartitionableBlockDeviceAPI parentApi; + private final PartitionableBlockDeviceAPI<PTE> parentApi; /** * @param parentApi * @param alignment */ - public PartitionableBlockAlignmentSupport(PartitionableBlockDeviceAPI parentApi, int alignment) { + public PartitionableBlockAlignmentSupport(PartitionableBlockDeviceAPI<PTE> parentApi, int alignment) { super(parentApi, alignment); this.parentApi = parentApi; } @@ -54,7 +56,7 @@ * @return Null if no partition table is found. * @throws IOException */ - public PartitionTable getPartitionTable() throws IOException { + public PartitionTable<PTE> getPartitionTable() throws IOException { return parentApi.getPartitionTable(); } } Modified: trunk/fs/src/driver/org/jnode/driver/block/PartitionableBlockDeviceAPI.java =================================================================== --- trunk/fs/src/driver/org/jnode/driver/block/PartitionableBlockDeviceAPI.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/driver/org/jnode/driver/block/PartitionableBlockDeviceAPI.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -24,6 +24,7 @@ import java.io.IOException; import org.jnode.partitions.PartitionTable; +import org.jnode.partitions.PartitionTableEntry; /** * This device API is implemented by block devices that @@ -31,7 +32,9 @@ * * @author Ewout Prangsma (ep...@us...) */ -public interface PartitionableBlockDeviceAPI extends BlockDeviceAPI { +public interface PartitionableBlockDeviceAPI + <PTE extends PartitionTableEntry> + extends BlockDeviceAPI { /** * Gets the sector size for this device. @@ -45,5 +48,5 @@ * @return Null if no partition table is found. * @throws IOException */ - public PartitionTable getPartitionTable() throws IOException; + public PartitionTable<PTE> getPartitionTable() throws IOException; } Modified: trunk/fs/src/driver/org/jnode/driver/block/ide/disk/IDEDiskDriver.java =================================================================== --- trunk/fs/src/driver/org/jnode/driver/block/ide/disk/IDEDiskDriver.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/driver/org/jnode/driver/block/ide/disk/IDEDiskDriver.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -52,11 +52,9 @@ import org.jnode.driver.bus.ide.command.IDEReadSectorsCommand; import org.jnode.driver.bus.ide.command.IDEWriteSectorsCommand; import org.jnode.naming.InitialNaming; -import org.jnode.partitions.PartitionTable; import org.jnode.partitions.ibm.IBMPartitionTable; import org.jnode.partitions.ibm.IBMPartitionTableEntry; import org.jnode.system.BootLog; -import org.jnode.util.ByteBufferUtils; import org.jnode.util.TimeoutException; /** @@ -64,7 +62,8 @@ * * @author epr */ -public class IDEDiskDriver extends Driver implements IDEDeviceAPI, IDEConstants { +public class IDEDiskDriver extends Driver + implements IDEDeviceAPI<IBMPartitionTableEntry>, IDEConstants { /** My logger */ private static final Logger log = Logger.getLogger(IDEDiskDriver.class); @@ -115,35 +114,23 @@ this.pt = factory.createIBMPartitionTable(bs, dev); int partIndex = 0; - final int max = pt.getLength(); - for (int i = 0; i < max; i++) { - final IBMPartitionTableEntry pte = (IBMPartitionTableEntry)pt.getEntry(i); + int i = 0; + for (IBMPartitionTableEntry pte : pt) { if(pte == null) { BootLog.warn("PartitionTableEntry #"+i+" is null"); } else if (pte.isValid()) { if (pte.isExtended()) { - //now we should have an filled vector in the pt - final List<IBMPartitionTableEntry> extendedPartitions = pt.getExtendedPartitions(); - log.info("Have "+ extendedPartitions.size()+ " Extended partitions found"); - - for(int iPart = 0 ; iPart < extendedPartitions.size() ; iPart++) - { - IBMPartitionTableEntry pteExt = - extendedPartitions.get(iPart); - registerPartition(devMan, dev, pteExt, partIndex); - - if(iPart < (extendedPartitions.size() -1)) - partIndex++; - } - + // Create partition devices for the extended partition + partIndex = registerExtendedPartition(devMan, dev, partIndex); } else { // Create a partition device. registerPartition(devMan, dev, pte, partIndex); } } partIndex++; + i++; } } catch (DeviceAlreadyRegisteredException ex) { throw new DriverException("Partition device is already known???? Probably a bug", ex); @@ -314,6 +301,34 @@ pdev.setDriver(new IDEDiskPartitionDriver()); devMan.register(pdev); } + + /** + * register all the partitions included in the extended partition + * @param devMan + * @param dev + * @param partIndex + * @return + * @throws DeviceAlreadyRegisteredException + * @throws DriverException + */ + private int registerExtendedPartition(DeviceManager devMan, IDEDevice dev, + int partIndex) throws DeviceAlreadyRegisteredException, DriverException + { + //now we should have an filled vector in the pt + final List<IBMPartitionTableEntry> extendedPartitions = pt.getExtendedPartitions(); + log.info("Have "+ extendedPartitions.size()+ " Extended partitions found"); + + for(int iPart = 0 ; iPart < extendedPartitions.size() ; iPart++) + { + IBMPartitionTableEntry pteExt = + extendedPartitions.get(iPart); + registerPartition(devMan, dev, pteExt, partIndex); + + if(iPart < (extendedPartitions.size() -1)) + partIndex++; + } + return partIndex; + } /** * @see org.jnode.driver.block.PartitionableBlockDeviceAPI#getSectorSize() @@ -327,7 +342,7 @@ * @return Null if no partition table is found. * @throws IOException */ - public PartitionTable getPartitionTable() throws IOException { + public IBMPartitionTable getPartitionTable() throws IOException { return pt; } } Modified: trunk/fs/src/driver/org/jnode/driver/bus/ide/IDEDeviceAPI.java =================================================================== --- trunk/fs/src/driver/org/jnode/driver/bus/ide/IDEDeviceAPI.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/driver/org/jnode/driver/bus/ide/IDEDeviceAPI.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -22,10 +22,12 @@ package org.jnode.driver.bus.ide; import org.jnode.driver.block.PartitionableBlockDeviceAPI; +import org.jnode.partitions.PartitionTableEntry; /** * @author epr */ -public interface IDEDeviceAPI extends PartitionableBlockDeviceAPI { +public interface IDEDeviceAPI <PTE extends PartitionTableEntry> + extends PartitionableBlockDeviceAPI<PTE> { // nothing different } Modified: trunk/fs/src/fs/org/jnode/fs/fat/BootSector.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/fat/BootSector.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/fs/org/jnode/fs/fat/BootSector.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -356,6 +356,11 @@ return dirty; } + public int getNbPartitions() + { + return partitions.length; + } + public synchronized IBMPartitionTableEntry getPartition(int partNr) { if (partitions[partNr] == null) { partitions[partNr] = new IBMPartitionTableEntry(null, data, partNr); Modified: trunk/fs/src/fs/org/jnode/fs/fat/FatFileSystemType.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/fat/FatFileSystemType.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/fs/org/jnode/fs/fat/FatFileSystemType.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -69,15 +69,17 @@ return false; } final IBMPartitionTableEntry ipte = (IBMPartitionTableEntry)pte; - final int type = ipte.getSystemIndicator(); - switch (type) { - case IBMPartitionTypes.PARTTYPE_DOS_FAT12 : - case IBMPartitionTypes.PARTTYPE_DOS_FAT16_LT32M : - case IBMPartitionTypes.PARTTYPE_DOS_FAT16_GT32M : - return true; - default : - return false; + final IBMPartitionTypes type = ipte.getSystemIndicator(); + if((type == IBMPartitionTypes.PARTTYPE_DOS_FAT12) || + (type == IBMPartitionTypes.PARTTYPE_DOS_FAT16_LT32M) || + (type == IBMPartitionTypes.PARTTYPE_DOS_FAT16_GT32M) ) + { + return true; } + else + { + return false; + } } Modified: trunk/fs/src/fs/org/jnode/fs/jfat/FatFileSystemType.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/jfat/FatFileSystemType.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/fs/org/jnode/fs/jfat/FatFileSystemType.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -43,18 +43,18 @@ return false; final IBMPartitionTableEntry ipte = - (IBMPartitionTableEntry)pte; + (IBMPartitionTableEntry)pte; - final int type = ipte.getSystemIndicator(); - - switch ( type ) { - case IBMPartitionTypes.PARTTYPE_WIN95_FAT32: - case IBMPartitionTypes.PARTTYPE_WIN95_FAT32_LBA: - return true; - - default: - return false; - } + final IBMPartitionTypes type = ipte.getSystemIndicator(); + if((type == IBMPartitionTypes.PARTTYPE_WIN95_FAT32) || + (type == IBMPartitionTypes.PARTTYPE_WIN95_FAT32_LBA) ) + { + return true; + } + else + { + return false; + } } return false; Modified: trunk/fs/src/fs/org/jnode/fs/ntfs/NTFSFileSystemType.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/ntfs/NTFSFileSystemType.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/fs/org/jnode/fs/ntfs/NTFSFileSystemType.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -52,8 +52,10 @@ FSBlockDeviceAPI devApi) { if (pte instanceof IBMPartitionTableEntry) { IBMPartitionTableEntry iPte = (IBMPartitionTableEntry) pte; - if (iPte.getSystemIndicator() == IBMPartitionTypes.PARTTYPE_NTFS) { return new String( - firstSector, 0x03, 8).startsWith(TAG); } + if (iPte.getSystemIndicator() == IBMPartitionTypes.PARTTYPE_NTFS) + { + return new String(firstSector, 0x03, 8).startsWith(TAG); + } } return false; } Modified: trunk/fs/src/fs/org/jnode/partitions/PartitionTable.java =================================================================== --- trunk/fs/src/fs/org/jnode/partitions/PartitionTable.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/fs/org/jnode/partitions/PartitionTable.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -24,21 +24,11 @@ /** * @author epr */ -public interface PartitionTable { +public interface PartitionTable <PTE extends PartitionTableEntry> + extends Iterable<PTE> { /** * Gets the type of this partition table */ public PartitionTableType getType(); - - /** - * Gets the number of entries in this table - */ - public int getLength(); - - /** - * Gets the partition table entry at the given index. - * @param index - */ - public PartitionTableEntry getEntry(int index); } Modified: trunk/fs/src/fs/org/jnode/partitions/command/FdiskCommand.java =================================================================== --- trunk/fs/src/fs/org/jnode/partitions/command/FdiskCommand.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/fs/org/jnode/partitions/command/FdiskCommand.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -25,7 +25,7 @@ import java.nio.ByteBuffer; import java.util.Collection; import java.util.List; -import java.util.StringTokenizer; +import java.util.NoSuchElementException; import javax.naming.NameNotFoundException; @@ -33,14 +33,12 @@ import org.jnode.driver.Device; import org.jnode.driver.DeviceManager; import org.jnode.driver.DeviceNotFoundException; -import org.jnode.driver.DriverException; import org.jnode.driver.block.BlockDeviceAPI; import org.jnode.driver.bus.ide.IDEConstants; import org.jnode.driver.bus.ide.IDEDevice; import org.jnode.driver.bus.ide.IDEDriveDescriptor; -import org.jnode.fs.fat.BootSector; -import org.jnode.fs.fat.GrubBootSector; import org.jnode.naming.InitialNaming; +import org.jnode.partitions.help.argument.IBMPartitionTypeArgument; import org.jnode.partitions.ibm.IBMPartitionTable; import org.jnode.partitions.ibm.IBMPartitionTableEntry; import org.jnode.partitions.ibm.IBMPartitionTableType; @@ -51,8 +49,11 @@ import org.jnode.shell.help.Syntax; import org.jnode.shell.help.SyntaxErrorException; import org.jnode.shell.help.argument.DeviceArgument; +import org.jnode.shell.help.argument.IntegerArgument; +import org.jnode.shell.help.argument.LongArgument; import org.jnode.shell.help.argument.OptionArgument; -import org.jnode.shell.help.argument.StringArgument; +import org.jnode.shell.help.argument.SizeArgument; + /** * @author gbin * @author Trickkiste @@ -72,50 +73,54 @@ "Action on a specified partition", new OptionArgument.Option[] { new OptionArgument.Option("-d", "Delete a partition"), - new OptionArgument.Option("-b", "Switch the bootable flag of a partition"), + new OptionArgument.Option("-b", "Switch the bootable flag of a partition")}); + + static final OptionArgument ACTION_MODIFY = + new OptionArgument( + "action", + "Action on a specified partition", + new OptionArgument.Option[] { new OptionArgument.Option("-m", "Modify/create a partition")}); - static final StringArgument PARTITION = new StringArgument("partition number", "Targeted partition"); - static final StringArgument PARTITION_DESCRIPTION = new StringArgument("description", "Partition description" + - " \"ID:start:size:filesystem\"" + - " ID : ID of the partition" + - " start : Sector where the partition starts" + - " size : Size of the partition in sectors" + - " filesystem : Number of the filesystem type"); + static final IntegerArgument PARTITION = new IntegerArgument("partition number", "Targeted partition"); + static final LongArgument START = new LongArgument("start", "Sector where the partition starts"); + static final SizeArgument SIZE = new SizeArgument("size", "Size of the partition in sectors or in bytes(use prefixes K, M, G, ...)"); + static final IBMPartitionTypeArgument PARTITION_TYPE = new IBMPartitionTypeArgument( + "partition type", "partition type code"); static final DeviceArgument ARG_DEVICE = new DeviceArgument("device-id", "the device on which you want to change/create the partition"); static final Parameter PARAM_INITMBR = new Parameter(INITMBR, Parameter.MANDATORY); static final Parameter PARAM_ACTION = new Parameter(ACTION, Parameter.MANDATORY); + static final Parameter PARAM_ACTION_MODIFY = new Parameter(ACTION_MODIFY, Parameter.MANDATORY); static final Parameter PARAM_DEVICE = new Parameter(ARG_DEVICE, Parameter.MANDATORY); static final Parameter PARAM_PARTITION = new Parameter(PARTITION, Parameter.MANDATORY); - static final Parameter PARAM_PARTITION_DESCRIPTION = new Parameter(PARTITION_DESCRIPTION, Parameter.MANDATORY); + static final Parameter PARAM_START = new Parameter(START, Parameter.MANDATORY); + static final Parameter PARAM_SIZE = new Parameter(SIZE, Parameter.MANDATORY); + static final Parameter PARAM_PARTITION_TYPE = new Parameter(PARTITION_TYPE, Parameter.MANDATORY); public static Help.Info HELP_INFO = new Help.Info( "fdisk", new Syntax[] { new Syntax("Lists the available devices"), - new Syntax("Print the partition table of a device", new Parameter[] { PARAM_DEVICE }), - new Syntax("Initialize the MBR of a device", new Parameter[] { PARAM_INITMBR, PARAM_DEVICE }), - new Syntax( - "Create / Delete / change a partition", - new Parameter[] { PARAM_ACTION, PARAM_PARTITION, PARAM_DEVICE }), - new Syntax( - "Create / Delete / change a partition", - new Parameter[] { PARAM_ACTION, PARAM_PARTITION_DESCRIPTION, PARAM_DEVICE }) + new Syntax("Print the partition table of a device", + new Parameter[] { + PARAM_DEVICE }), + new Syntax("Initialize the MBR of a device", + new Parameter[] { + PARAM_INITMBR, PARAM_DEVICE }), + new Syntax("Change a partition", + new Parameter[] { + PARAM_ACTION_MODIFY, PARAM_PARTITION, PARAM_START, + PARAM_SIZE, PARAM_PARTITION_TYPE, + PARAM_DEVICE }), + new Syntax("Delete a partition / switch bootable flag", + new Parameter[] { + PARAM_ACTION, PARAM_PARTITION, PARAM_DEVICE }), }); - /* - * public static Help.Info HELP_INFO = new Help.Info( "fdisk", "With no - * argument, it lists the available devices\n" + "With only the device, it - * lists the current partitions on the device\n" + "--initmbr initialize the - * Master Boot Record of the device\n" + "-m add or modify the id partition - * with first sector at start, size of size sectors and fs id fs\n" + "-d - * delete the partition with id id" + "-b switch boot flag on parition id", - */ - public static void main(String[] args) throws SyntaxErrorException { ParsedArguments cmdLine = HELP_INFO.parse(args); @@ -124,6 +129,7 @@ dm = InitialNaming.lookup(DeviceManager.NAME); boolean isAction = PARAM_ACTION.isSet(cmdLine); + boolean isActionModify = PARAM_ACTION_MODIFY.isSet(cmdLine); boolean isInitMBR = PARAM_INITMBR.isSet(cmdLine); boolean isDevice = PARAM_DEVICE.isSet(cmdLine); @@ -134,56 +140,41 @@ } // only device is set - if (!isAction && !isInitMBR && isDevice) { + if (!isAction && !isActionModify && !isInitMBR && isDevice) { printTable(ARG_DEVICE.getValue(cmdLine), dm); return; } + final String deviceId = ARG_DEVICE.getValue(cmdLine); + final PartitionHelper helper = new PartitionHelper(deviceId, dm); + // initMBR if (isInitMBR) { - initMbr(ARG_DEVICE.getValue(cmdLine), dm); + helper.initMbr(); + helper.write(); return; } - // now it is a change on a specific partition so read the table + int partNumber = getPartitionNumber(helper, cmdLine); - IDEDevice current = (IDEDevice)dm.getDevice(ARG_DEVICE.getValue(cmdLine)); - BlockDeviceAPI api = current.getAPI(BlockDeviceAPI.class); - ByteBuffer mbr = ByteBuffer.allocate(IDEConstants.SECTOR_SIZE); - api.read(0, mbr); - if (!IBMPartitionTable.containsPartitionTable(mbr.array())) - throw new IOException("This device doesn't contain a valid MBR, use --initmbr."); - - BootSector bs = new BootSector(mbr.array()); - - if (ACTION.getValue(cmdLine).intern() == "-m") { - modifyPartition(PARTITION.getValue(cmdLine), api, bs, current); - bs.write(api); + // modify a partition ? + if (ACTION_MODIFY.getValue(cmdLine).intern() == "-m") { + modifyPartition(helper, partNumber, cmdLine); + helper.write(); return; } - // it is not a modify so the PARTITION parameter is only a partition - // number - - int partNumber; - try { - partNumber = Integer.parseInt(PARTITION.getValue(cmdLine)); - } catch (NumberFormatException f) { - throw new IllegalArgumentException("Partition number is invalid"); - } - - if (partNumber > 3 || partNumber < 0) - throw new IllegalArgumentException("Partition number is invalid"); - + // delete a partition ? if (ACTION.getValue(cmdLine).intern() == "-d") { - deletePartition(bs, partNumber); - bs.write(api); + helper.deletePartition(partNumber); + helper.write(); return; } + // toggle boot flag for a partition ? if (ACTION.getValue(cmdLine).intern() == "-b") { - toggleBootable(bs, partNumber); - bs.write(api); + helper.toggleBootable(partNumber); + helper.write(); } } catch (IOException e) { e.printStackTrace(); @@ -194,99 +185,56 @@ } catch (DeviceNotFoundException e) { e.printStackTrace(); } - } + + private static int getPartitionNumber(PartitionHelper helper, ParsedArguments cmdLine) + { + int partNumber = PARTITION.getInteger(cmdLine); - private static void toggleBootable(BootSector bs, int partNumber) { - // save the current state for the targeted partition - boolean currentStatus = bs.getPartition(partNumber).getBootIndicator(); - - // erase all the states - for (int i = 0; i < 4; i++) { - bs.getPartition(i).setBootIndicator(false); - } - - // put back the reversed state for the targeted partition - bs.getPartition(partNumber).setBootIndicator(!currentStatus); + if ((partNumber >= helper.getNbPartitions()) || + (partNumber < 0) ) + throw new IllegalArgumentException("Partition number is invalid"); + + return partNumber; } - private static void deletePartition(BootSector bs, int partNumber) { - bs.getPartition(partNumber).setSystemIndicator(IBMPartitionTypes.PARTTYPE_EMPTY); - } - - private static void modifyPartition(String description, BlockDeviceAPI api, BootSector bs, Device dev) throws IOException { - // arg 1 should be in the form id:start:size:fs - StringTokenizer st = new StringTokenizer(description, ":"); - int id = Integer.parseInt(st.nextToken()); - //BUG in long - //long start = Long.parseLong(st.nextToken()); - //long size = Long.parseLong(st.nextToken()); - int start = Integer.parseInt(st.nextToken()); - int size = Integer.parseInt(st.nextToken()); - int fs = Integer.parseInt(st.nextToken(), 16); - System.out.println( - "Init " + id + " with start = " + start + ", size = " + size + ", fs = " + Integer.toHexString(fs & 0xff)); - IBMPartitionTableEntry entry = bs.getPartition(id); - entry.setBootIndicator(false); - entry.setSystemIndicator(fs); - entry.setStartLba(start); - entry.setNrSectors(size); - bs.write(api); - -// restart the device - DeviceManager dm = null; - - try { - dm = InitialNaming.lookup(DeviceManager.NAME); - dm.stop(dev); - dm.start(dev); + private static void modifyPartition(PartitionHelper helper, + int id, + ParsedArguments cmdLine) + throws IOException + { + long start = START.getLong(cmdLine); + long size = SIZE.getLong(cmdLine); + IBMPartitionTypes type = PARTITION_TYPE.getArgValue(cmdLine); - } catch (NameNotFoundException e) { - - e.printStackTrace(); - } catch (DeviceNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (DriverException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - - return; +// try { + System.out.println("D"); + System.out.println("Init " + id + " with start = " + start + + ", size = " + size + ", fs = " + + Integer.toHexString(type.getCode() & 0xff)); + System.out.println("E"); + boolean sizeUnit = SIZE.hasSizeUnit(cmdLine) ? + PartitionHelper.BYTES : PartitionHelper.SECTORS; + helper.modifyPartition(id, false, start, size, sizeUnit, type); + System.out.println("F"); +// } +// catch (NumberFormatException nfe) +// { +// System.err.println("not an integer"); +// System.err.println(helpMsg); +// } +// catch (NoSuchElementException nsee) +// { +// System.err.println("not enough elements"); +// System.err.println(helpMsg); +// } +// catch (IllegalArgumentException iae) +// { +// System.err.println(iae.getMessage()); +// System.err.println(helpMsg); +// } } - - private static void initMbr(String device, DeviceManager dm) - throws DeviceNotFoundException, ApiNotFoundException, IOException { - IDEDevice current = (IDEDevice)dm.getDevice(device); - BlockDeviceAPI api = current.getAPI(BlockDeviceAPI.class); - ByteBuffer MBR = ByteBuffer.allocate(IDEConstants.SECTOR_SIZE); - api.read(0, MBR); - - System.out.println("Initialize MBR ..."); - - GrubBootSector newMBR = new GrubBootSector(PLAIN_MASTER_BOOT_SECTOR); - - if (IBMPartitionTable.containsPartitionTable(MBR.array())) { - BootSector oldMBR = new BootSector(MBR.array()); - System.out.println("This device already contains a partition table. Copy the already existing partitions."); - for (int i = 0; i < 4; i++) { - IBMPartitionTableEntry entry = newMBR.getPartition(i); - entry.setBootIndicator(oldMBR.getPartition(i).getBootIndicator()); - entry.setStartLba(oldMBR.getPartition(i).getStartLba()); - entry.setNrSectors(oldMBR.getPartition(i).getNrSectors()); - entry.setSystemIndicator(oldMBR.getPartition(i).getSystemIndicator()); - - } - } else { - newMBR.getPartition(0).setSystemIndicator(IBMPartitionTypes.PARTTYPE_EMPTY); - newMBR.getPartition(1).setSystemIndicator(IBMPartitionTypes.PARTTYPE_EMPTY); - newMBR.getPartition(2).setSystemIndicator(IBMPartitionTypes.PARTTYPE_EMPTY); - newMBR.getPartition(3).setSystemIndicator(IBMPartitionTypes.PARTTYPE_EMPTY); - } - newMBR.write(api); - } - + private static void printTable(String deviceName, DeviceManager dm) throws DeviceNotFoundException, ApiNotFoundException, IOException { { @@ -297,16 +245,16 @@ api.read(0, MBR); if (IBMPartitionTable.containsPartitionTable(MBR.array())) { IBMPartitionTable partitionTable = new IBMPartitionTable(new IBMPartitionTableType(), MBR.array(), current); - int nbPartitions = partitionTable.getLength(); System.out.println( "Disk : " + current.getId() + ": " + descriptor.getSectorsIn28bitAddressing() * 512 + " bytes"); System.out.println("Device Boot Start End Blocks System"); - for (int i = 0; i < nbPartitions; i++) { - IBMPartitionTableEntry entry = (IBMPartitionTableEntry)partitionTable.getEntry(i); - int si = entry.getSystemIndicator(); - if (si != 0) + int i = 0; + for (IBMPartitionTableEntry entry : partitionTable) { + //IBMPartitionTableEntry entry = (IBMPartitionTableEntry)partitionTable.getEntry(i); + IBMPartitionTypes si = entry.getSystemIndicator(); + if (si != IBMPartitionTypes.PARTTYPE_EMPTY) System.out.println( "ID " + i @@ -319,7 +267,7 @@ + " " + entry.getNrSectors() + " " - + Integer.toHexString(si)); + + si); if(entry.isExtended()) { final List<IBMPartitionTableEntry> exPartitions = partitionTable.getExtendedPartitions(); int j = 0; @@ -337,11 +285,11 @@ + " " + "-----"//exEntry.getNrSectors() + " " - + Integer.toHexString(si)); + + si); j++; } } - + i++; } } else { @@ -371,520 +319,4 @@ } } } - - private static final byte PLAIN_MASTER_BOOT_SECTOR[] = - { - (byte)0xEB, - (byte)0x48, - (byte)0x90, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x03, - (byte)0x02, - (byte)0xFF, - (byte)0x00, - (byte)0x00, - (byte)0x80, - (byte)0x01, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x08, - (byte)0xFA, - (byte)0xEA, - (byte)0x50, - (byte)0x7C, - (byte)0x00, - (byte)0x00, - (byte)0x31, - (byte)0xC0, - (byte)0x8E, - (byte)0xD8, - (byte)0x8E, - (byte)0xD0, - (byte)0xBC, - (byte)0x00, - (byte)0x20, - (byte)0xFB, - (byte)0xA0, - (byte)0x40, - (byte)0x7C, - (byte)0x3C, - (byte)0xFF, - (byte)0x74, - (byte)0x02, - (byte)0x88, - (byte)0xC2, - (byte)0x52, - (byte)0xBE, - (byte)0x76, - (byte)0x7D, - (byte)0xE8, - (byte)0x34, - (byte)0x01, - (byte)0xF6, - (byte)0xC2, - (byte)0x80, - (byte)0x74, - (byte)0x54, - (byte)0xB4, - (byte)0x41, - (byte)0xBB, - (byte)0xAA, - (byte)0x55, - (byte)0xCD, - (byte)0x13, - (byte)0x5A, - (byte)0x52, - (byte)0x72, - (byte)0x49, - (byte)0x81, - (byte)0xFB, - (byte)0x55, - (byte)0xAA, - (byte)0x75, - (byte)0x43, - (byte)0xA0, - (byte)0x41, - (byte)0x7C, - (byte)0x84, - (byte)0xC0, - (byte)0x75, - (byte)0x05, - (byte)0x83, - (byte)0xE1, - (byte)0x01, - (byte)0x74, - (byte)0x37, - (byte)0x66, - (byte)0x8B, - (byte)0x4C, - (byte)0x10, - (byte)0xBE, - (byte)0x05, - (byte)0x7C, - (byte)0xC6, - (byte)0x44, - (byte)0xFF, - (byte)0x01, - (byte)0x66, - (byte)0x8B, - (byte)0x1E, - (byte)0x44, - (byte)0x7C, - (byte)0xC7, - (byte)0x04, - (byte)0x10, - (byte)0x00, - (byte)0xC7, - (byte)0x44, - (byte)0x02, - (byte)0x01, - (byte)0x00, - (byte)0x66, - (byte)0x89, - (byte)0x5C, - (byte)0x08, - (byte)0xC7, - (byte)0x44, - (byte)0x06, - (byte)0x00, - (byte)0x70, - (byte)0x66, - (byte)0x31, - (byte)0xC0, - (byte)0x89, - (byte)0x44, - (byte)0x04, - (byte)0x66, - (byte)0x89, - (byte)0x44, - (byte)0x0C, - (byte)0xB4, - (byte)0x42, - (byte)0xCD, - (byte)0x13, - (byte)0x72, - (byte)0x05, - (byte)0xBB, - (byte)0x00, - (byte)0x70, - (byte)0xEB, - (byte)0x7D, - (byte)0xB4, - (byte)0x08, - (byte)0xCD, - (byte)0x13, - (byte)0x73, - (byte)0x0A, - (byte)0xF6, - (byte)0xC2, - (byte)0x80, - (byte)0x0F, - (byte)0x84, - (byte)0xF3, - (byte)0x00, - (byte)0xE9, - (byte)0x8D, - (byte)0x00, - (byte)0xBE, - (byte)0x05, - (byte)0x7C, - (byte)0xC6, - (byte)0x44, - (byte)0xFF, - (byte)0x00, - (byte)0x66, - (byte)0x31, - (byte)0xC0, - (byte)0x88, - (byte)0xF0, - (byte)0x40, - (byte)0x66, - (byte)0x89, - (byte)0x44, - (byte)0x04, - (byte)0x31, - (byte)0xD2, - (byte)0x88, - (byte)0xCA, - (byte)0xC1, - (byte)0xE2, - (byte)0x02, - (byte)0x88, - (byte)0xE8, - (byte)0x88, - (byte)0xF4, - (byte)0x40, - (byte)0x89, - (byte)0x44, - (byte)0x08, - (byte)0x31, - (byte)0xC0, - (byte)0x88, - (byte)0xD0, - (byte)0xC0, - (byte)0xE8, - (byte)0x02, - (byte)0x66, - (byte)0x89, - (byte)0x04, - (byte)0x66, - (byte)0xA1, - (byte)0x44, - (byte)0x7C, - (byte)0x66, - (byte)0x31, - (byte)0xD2, - (byte)0x66, - (byte)0xF7, - (byte)0x34, - (byte)0x88, - (byte)0x54, - (byte)0x0A, - (byte)0x66, - (byte)0x31, - (byte)0xD2, - (byte)0x66, - (byte)0xF7, - (byte)0x74, - (byte)0x04, - (byte)0x88, - (byte)0x54, - (byte)0x0B, - (byte)0x89, - (byte)0x44, - (byte)0x0C, - (byte)0x3B, - (byte)0x44, - (byte)0x08, - (byte)0x7D, - (byte)0x3C, - (byte)0x8A, - (byte)0x54, - (byte)0x0D, - (byte)0xC0, - (byte)0xE2, - (byte)0x06, - (byte)0x8A, - (byte)0x4C, - (byte)0x0A, - (byte)0xFE, - (byte)0xC1, - (byte)0x08, - (byte)0xD1, - (byte)0x8A, - (byte)0x6C, - (byte)0x0C, - (byte)0x5A, - (byte)0x8A, - (byte)0x74, - (byte)0x0B, - (byte)0xBB, - (byte)0x00, - (byte)0x70, - (byte)0x8E, - (byte)0xC3, - (byte)0x31, - (byte)0xDB, - (byte)0xB8, - (byte)0x01, - (byte)0x02, - (byte)0xCD, - (byte)0x13, - (byte)0x72, - (byte)0x2A, - (byte)0x8C, - (byte)0xC3, - (byte)0x8E, - (byte)0x06, - (byte)0x48, - (byte)0x7C, - (byte)0x60, - (byte)0x1E, - (byte)0xB9, - (byte)0x00, - (byte)0x01, - (byte)0x8E, - (byte)0xDB, - (byte)0x31, - (byte)0xF6, - (byte)0x31, - (byte)0xFF, - (byte)0xFC, - (byte)0xF3, - (byte)0xA5, - (byte)0x1F, - (byte)0x61, - (byte)0xFF, - (byte)0x26, - (byte)0x42, - (byte)0x7C, - (byte)0xBE, - (byte)0x7C, - (byte)0x7D, - (byte)0xE8, - (byte)0x40, - (byte)0x00, - (byte)0xEB, - (byte)0x0E, - (byte)0xBE, - (byte)0x81, - (byte)0x7D, - (byte)0xE8, - (byte)0x38, - (byte)0x00, - (byte)0xEB, - (byte)0x06, - (byte)0xBE, - (byte)0x8B, - (byte)0x7D, - (byte)0xE8, - (byte)0x30, - (byte)0x00, - (byte)0xBE, - (byte)0x90, - (byte)0x7D, - (byte)0xE8, - (byte)0x2A, - (byte)0x00, - (byte)0xEB, - (byte)0xFE, - (byte)0x47, - (byte)0x52, - (byte)0x55, - (byte)0x42, - (byte)0x20, - (byte)0x00, - (byte)0x47, - (byte)0x65, - (byte)0x6F, - (byte)0x6D, - (byte)0x00, - (byte)0x48, - (byte)0x61, - (byte)0x72, - (byte)0x64, - (byte)0x20, - (byte)0x44, - (byte)0x69, - (byte)0x73, - (byte)0x6B, - (byte)0x00, - (byte)0x52, - (byte)0x65, - (byte)0x61, - (byte)0x64, - (byte)0x00, - (byte)0x20, - (byte)0x45, - (byte)0x72, - (byte)0x72, - (byte)0x6F, - (byte)0x72, - (byte)0x00, - (byte)0xBB, - (byte)0x01, - (byte)0x00, - (byte)0xB4, - (byte)0x0E, - (byte)0xCD, - (byte)0x10, - (byte)0xAC, - (byte)0x3C, - (byte)0x00, - (byte)0x75, - (byte)0xF4, - (byte)0xC3, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x24, - (byte)0x12, - (byte)0x0F, - (byte)0x09, - (byte)0x00, - (byte)0xBE, - (byte)0xBD, - (byte)0x7D, - (byte)0x31, - (byte)0xC0, - (byte)0xCD, - (byte)0x13, - (byte)0x46, - (byte)0x8A, - (byte)0x0C, - (byte)0x80, - (byte)0xF9, - (byte)0x00, - (byte)0x75, - (byte)0x0F, - (byte)0xBE, - (byte)0xDA, - (byte)0x7D, - (byte)0xE8, - (byte)0xC6, - (byte)0xFF, - (byte)0xEB, - (byte)0x94, - (byte)0x46, - (byte)0x6C, - (byte)0x6F, - (byte)0x70, - (byte)0x70, - (byte)0x79, - (byte)0x00, - (byte)0xBB, - (byte)0x00, - (byte)0x70, - (byte)0xB8, - (byte)0x01, - (byte)0x02, - (byte)0xB5, - (byte)0x00, - (byte)0xB6, - (byte)0x00, - (byte)0xCD, - (byte)0x13, - (byte)0x72, - (byte)0xD7, - (byte)0xB6, - (byte)0x01, - (byte)0xB5, - (byte)0x4F, - (byte)0xE9, - (byte)0xDD, - (byte)0xFE, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x00, - (byte)0x55, - (byte)0xAA }; - } Modified: trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTable.java =================================================================== --- trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTable.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTable.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -24,6 +24,9 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; import java.util.List; import org.apache.log4j.Logger; @@ -38,7 +41,7 @@ /** * @author epr */ -public class IBMPartitionTable implements PartitionTable { +public class IBMPartitionTable implements PartitionTable<IBMPartitionTableEntry> { /** The type of partition table */ private final IBMPartitionTableType tableType; @@ -66,9 +69,9 @@ public IBMPartitionTable(IBMPartitionTableType tableType, byte[] bootSector, Device device) { //this.bootSector = bootSector; this.tableType = tableType; - this.partitions = new IBMPartitionTableEntry[4]; this.drivedDevice = device; if(containsPartitionTable(bootSector)) { + this.partitions = new IBMPartitionTableEntry[4]; for (int partNr = 0; partNr < partitions.length ; partNr++) { log.debug("try part "+ partNr); partitions[partNr] = new IBMPartitionTableEntry(this, bootSector, partNr); @@ -79,6 +82,10 @@ } } } + else + { + partitions = null; + } } /** @@ -142,22 +149,28 @@ return true; } - /** - * Gets the number of partitions in this table. - */ - public int getLength() { - return partitions.length; + public Iterator<IBMPartitionTableEntry> iterator() { + return new Iterator<IBMPartitionTableEntry>() + { + private int index = 0; + private final int last = (partitions == null) ? 0 : + partitions.length - 1; + + public boolean hasNext() { + return index < last; + } + + public IBMPartitionTableEntry next() { + return partitions[index++]; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; } /** - * Gets a single entry. - * @param partNr - */ - public PartitionTableEntry getEntry(int partNr) { - return partitions[partNr]; - } - - /** * @return Returns the extendedPartitions. */ public List<IBMPartitionTableEntry> getExtendedPartitions() { Modified: trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTableEntry.java =================================================================== --- trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTableEntry.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTableEntry.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -54,7 +54,7 @@ /** * @see org.jnode.partitions.PartitionTableEntry#getChildPartitionTable() */ - public PartitionTable getChildPartitionTable() { + public IBMPartitionTable getChildPartitionTable() { throw new Error("Not implemented yet"); } @@ -71,7 +71,7 @@ public boolean isExtended() { - final int id = getSystemIndicator(); + final IBMPartitionTypes id = getSystemIndicator(); //pgwiasda //there are more than one type of extended Partitions return (id == IBMPartitionTypes.PARTTYPE_WIN95_FAT32_EXTENDED || @@ -105,12 +105,12 @@ LittleEndian.setInt8(bs, ofs+3, chs.getCylinder() & 0xFF); } - public int getSystemIndicator() { - return LittleEndian.getUInt8(bs, ofs+4); + public IBMPartitionTypes getSystemIndicator() { + return IBMPartitionTypes.valueOf(LittleEndian.getUInt8(bs, ofs+4)); } - public void setSystemIndicator(int v) { - LittleEndian.setInt8(bs, ofs+4, v); + public void setSystemIndicator(IBMPartitionTypes type) { + LittleEndian.setInt8(bs, ofs+4, type.getCode()); } public CHS getEndCHS() { @@ -171,7 +171,7 @@ b.append(getBootIndicator() ? 'A' : ' '); b.append(' '); - b.append(NumberUtils.hex(getSystemIndicator(), 2)); + b.append(NumberUtils.hex(getSystemIndicator().getCode(), 2)); b.append(' '); b.append("s:"+getStartLba()); b.append(' '); Modified: trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTypes.java =================================================================== --- trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTypes.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/fs/org/jnode/partitions/ibm/IBMPartitionTypes.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -25,104 +25,122 @@ * @author epr * **/ -public interface IBMPartitionTypes { +public enum IBMPartitionTypes { + PARTTYPE_EMPTY (0x00, "empty"), + PARTTYPE_DOS_FAT12 (0x01, "DOS 12-bit FAT"), + PARTTYPE_XENIX_ROOT (0x02, "XENIX root file system"), + PARTTYPE_XENIX_USR (0x03, "XENIX /usr file system (obsolete)"), + PARTTYPE_DOS_FAT16_LT32M (0x04, "DOS 16-bit FAT (up to 32M)"), + PARTTYPE_DOS_EXTENDED (0x05, "DOS 3.3+ extended partition"), + PARTTYPE_DOS_FAT16_GT32M (0x06, "DOS 3.31+ Large File System (16-bit FAT, over 32M)"), + PARTTYPE_NTFS (0x07, "NTFS, OS/2 HPFS, Advanced Unix"), + PARTTYPE_AIX_BOOTABLE (0x08, "AIX bootable partition, SplitDrive"), + PARTTYPE_AIX_DATA (0x09, "AIX data partition, Coherent filesystem"), + PARTTYPE_OS2_BOOT_MANAGER (0x0A, "OS/2 Boot Manager, OPUS, Coherent swap partition"), + PARTTYPE_WIN95_FAT32 (0x0B, "Win 95 Fat Partition"), + PARTTYPE_WIN95_FAT32_LBA (0x0C, "Win 95 Fat 32 Partition (LBA)"), + PARTTYPE_WIN95_FAT16_LBA (0x0E, "Win 95 Fat 16 Partition (LBA)"), + PARTTYPE_WIN95_FAT32_EXTENDED (0x0F, "WIN95 EXTENDED"), + PARTTYPE_OPUS (0x10, "OPUS"), + PARTTYPE_OS2_BOOT_HIDDEN_12 (0x11, "OS/2 Boot Manager hidden 12-bit FAT partition"), + PARTTYPE_COMPAQ_DIAG (0x12, "Compaq Diagnostics partition"), + PARTTYPE_OS2_BOOT_HIDDEN_16_S32 (0x14, "(resulted from using Novell DOS 7.0 FDISK to delete Linux Native part), OS/2 Boot Manager hidden sub-32M 16-bit FAT partition"), + PARTTYPE_OS2_BOOT_HIDDEN_16_O32 (0x16, "OS/2 Boot Manager hidden over-32M 16-bit FAT partition"), + PARTTYPE_OS2_BOOT_HIDDEN_HPFS (0x17, "OS/2 Boot Manager hidden HPFS partition"), + PARTTYPE_WINDOWS_SWAP (0x18, "AST special Windows swap file"), + PARTTYPE_WIN95_FAT_16_HIDDEN (0x1B, "Hidden Win95"), + PARTTYPE_WIN95_FAT_32_HIDDEN (0x1E, "Hidden Win95"), + PARTTYPE_NEC_MSDOS (0x24, "NEC MS-DOS 3.x"), + PARTTYPE_PLAN_9 (0x39, "Plan 9"), + PARTTYPE_POWERQUEST_RECOVERY (0x3C, "PowerQuest PartitionMagic recovery partition"), + PARTTYPE_VENIX80286 (0x40, "VENIX 80286"), + PARTTYPE_PPC_BOOT (0x41, "PPC_BOOT"), + PARTTYPE_SFS (0x42, "SFS (Secure File System) by Peter Gutmann"), + PARTTYPE_QNX (0x4d, "QNX"), + PARTTYPE_QNX_SECOND (0x4e, "QNX second Part"), + PARTTYPE_QNX_THIRD (0x4f, "QNX third Part"), + PARTTYPE_DISK_MANAGER_RO (0x50, "Disk Manager, read-only partition"), + PARTTYPE_DISK_MANAGER_RW (0x51, "Disk Manager, read/write partition, Novell???"), + PARTTYPE_CPM (0x52, "CP/M, Microport System V/386"), + PARTTYPE_ONTRACK_AUX (0x53, "Ontrack ?"), + PARTTYPE_ONTRACK (0x54, "Ontrack ?"), + PARTTYPE_EZ_DRIVE (0x55, "EZ_DRIVE"), + PARTTYPE_VFEATURE (0x56, "GoldenBow VFeature"), + PARTTYPE_PRIAM_EDISK (0x5c, "Priam Edisk"), + PARTTYPE_SPEEDSTOR (0x61, "SpeedStor"), + PARTTYPE_UNIX_SYS_V (0x63, "Unix SysV/386, 386/ix; ach, MtXinu BSD 4.3 on Mach; GNU HURD"), + PARTTYPE_NOVELL (0x64, "Novell NetWare"), + PARTTYPE_NOVELL_31 (0x65, "Novell NetWare (3.11)"), + PARTTYPE_DISK_SECURE (0x70, "DiskSecure Multi-Boot"), + PARTTYPE_PC_IX (0x75, "PC/IX"), + PARTTYPE_MINIX (0x80, "Minix v1.1 - 1.4a"), + PARTTYPE_LINUX (0x81, "Linux; Mitac Advanced Disk Manager"), + PARTTYPE_LINUX_SWAP (0x82, "Linux Swap partition"), + PARTTYPE_LINUXNATIVE (0x83, "Linux native file system (ext2fs/xiafs)"), + PARTTYPE_OS2_HIDING_DOS (0x84, "OS/2-renumbered type 04h partition (related to hiding DOS C: drive);"), + PARTTYPE_LINUX_EXTENDED (0x85, "Linux extendet partition"), + PARTTYPE_LINUX_LVM (0x8E, "Linux LVM"), + PARTTYPE_AMOEBA (0x93, "Amoeba file system"), + PARTTYPE_AMOEBA_BAD_BLOCK (0x94, "Amoeba bad block table"), + PARTTYPE_BSD (0x9F, "BSD"), + PARTTYPE_THIK_PAD_HIDDEN (0xA0, "IBM Thinkpad hidden partition"), + PARTTYPE_FREE_BSD (0xA5, "FreeBSD"), + PARTTYPE_OPEN_BSD (0xA6, "OpenBSD"), + PARTTYPE_NEXT_STEP (0xA7, "NextStep"), + PARTTYPE_NETBSD (0xA9, "NetBSD"), + PARTTYPE_BSDI (0xB7, "BSDI file system (secondarily swap)"), + PARTTYPE_BSDI_SWAP (0xB8, "BSDI swap partition (secondarily file system)"), + PARTTYPE_DR_DOS_12 (0xC1, "DR-DOS 6.0 LOGIN.EXE-secured 12-bit FAT partition;"), + PARTTYPE_DR_DOS_16 (0xC4, "DR-DOS 6.0 LOGIN.EXE-secured 16-bit FAT partition"), + PARTTYPE_DR_DOS_HUGE (0xC6, "DR-DOS 6.0 LOGIN.EXE-secured Huge partition"), + PARTTYPE_CYRNIX (0xC7, "Cyrnix Boot;"), + PARTTYPE_NON_FS (0xDA, "Non FS Data;"), + PARTTYPE_CPM_DOS (0xDB, "CP/M, Concurrent CP/M, Concurrent DOS; CTOS (Convergent Technologies OS)"), + PARTTYPE_DELL_UTILITY (0xDE, "DELL Utility partition"), + PARTTYPE_BOOT_IT (0xDF, "Boot it"), + PARTTYPE_SPEEDSTOR_FAT_12 (0xE1, "SpeedStor 12-bit FAT extended partition"), + PARTTYPE_DOS_R_O (0xE3, "Readonly Dos Partition"), + PARTTYPE_SPEEDSTOR_FAT_16 (0xE4, "SpeedStor 16-bit FAT extended partition"), + PARTTYPE_BEOS_FS (0xEB, "BEO_FS"), + PARTTYPE_EFI_GPT (0xEE, "EFI GPT"), + PARTTYPE_EFI_FAT (0xEF, "BEO_FS"), + PARTTYPE_LINUX_PA_RISK (0xF0, "Linux PA Risk"), + PARTTYPE_SPEEDSTORE_A (0xF1, "Speedstore ???"), + PARTTYPE_DOS3_3_SECENDORY (0xF2, "DOS 3.3+ secondary"), + PARTTYPE_SPEEDSTORE_B (0xF4, "Speedstore ???"), + PARTTYPE_LINUX_RAID (0xFD, "Linux Raid"), + PARTTYPE_LANSTEP (0xFE, "LANstep"), + PARTTYPE_XENIX_BAD_BLOCK (0xFF, "Xenix bad block table"); - public static final int PARTTYPE_EMPTY = 0x00; // empty - public static final int PARTTYPE_DOS_FAT12 = 0x01; // DOS 12-bit FAT - public static final int PARTTYPE_XENIX_ROOT = 0x02; // XENIX root file system - public static final int PARTTYPE_XENIX_USR = 0x03; // XENIX /usr file system (obsolete) - public static final int PARTTYPE_DOS_FAT16_LT32M = 0x04; // DOS 16-bit FAT (up to 32M) - public static final int PARTTYPE_DOS_EXTENDED = 0x05; // DOS 3.3+ extended partition - public static final int PARTTYPE_DOS_FAT16_GT32M = 0x06; // DOS 3.31+ Large File System (16-bit FAT, over 32M) - public static final int PARTTYPE_NTFS = 0x07; // NTFS - // OS/2 HPFS - // Advanced Unix - public static final int PARTTYPE_AIX_BOOTABLE = 0x08; // AIX bootable partition, SplitDrive - public static final int PARTTYPE_AIX_DATA = 0x09; // AIX data partition; - // Coherent filesystem; - public static final int PARTTYPE_OS2_BOOT_MANAGER = 0x0A; // OS/2 Boot Manager - // OPUS - // Coherent swap partition - public static final int PARTTYPE_WIN95_FAT32 = 0x0B; // Win 95 Fat Partition - public static final int PARTTYPE_WIN95_FAT32_LBA = 0x0C; // Win 95 Fat 32 Partition (LBA) - public static final int PARTTYPE_WIN95_FAT16_LBA = 0x0E; // Win 95 Fat 16 Partition (LBA) - public static final int PARTTYPE_WIN95_FAT32_EXTENDED = 0x0F; // WIN95 EXTENDED - public static final int PARTTYPE_OPUS = 0x10; // OPUS - public static final int PARTTYPE_OS2_BOOT_HIDDEN_12 = 0x11; // OS/2 Boot Manager hidden 12-bit FAT partition - public static final int PARTTYPE_COMPAQ_DIAG = 0x12; // Compaq Diagnostics partition - public static final int PARTTYPE_OS2_BOOT_HIDDEN_16_S32 = 0x14; // (resulted from using Novell DOS 7.0 FDISK to delete Linux Native part) - // OS/2 Boot Manager hidden sub-32M 16-bit FAT partition - public static final int PARTTYPE_OS2_BOOT_HIDDEN_16_O32 = 0x16; // OS/2 Boot Manager hidden over-32M 16-bit FAT partition - public static final int PARTTYPE_OS2_BOOT_HIDDEN_HPFS = 0x17; // OS/2 Boot Manager hidden HPFS partition - public static final int PARTTYPE_WINDOWS_SWAP = 0x18; // AST special Windows swap file - public static final int PARTTYPE_WIN95_FAT_16_HIDDEN = 0x1B; // Hidden Win95 - public static final int PARTTYPE_WIN95_FAT_32_HIDDEN = 0x1E; // Hidden Win95 - public static final int PARTTYPE_NEC_MSDOS = 0x24; // NEC MS-DOS 3.x - public static final int PARTTYPE_PLAN_9 = 0x39; // Plan 9 - public static final int PARTTYPE_POWERQUEST_RECOVERY = 0x3C; // PowerQuest PartitionMagic recovery partition - public static final int PARTTYPE_VENIX80286 = 0x40; // VENIX 80286 - public static final int PARTTYPE_PPC_BOOT = 0x41; // PPC_BOOT - public static final int PARTTYPE_SFS = 0x42; // SFS (Secure File System) by Peter Gutmann - public static final int PARTTYPE_QNX = 0x4d; // QNX - public static final int PARTTYPE_QNX_SECOND = 0x4e; // QNX second Part - public static final int PARTTYPE_QNX_THIRD = 0x4f; // QNX third Part - public static final int PARTTYPE_DISK_MANAGER_RO = 0x50; // Disk Manager, read-only partition - public static final int PARTTYPE_DISK_MANAGER_RW = 0x51; // Disk Manager, read/write partition - // Novell??? - public static final int PARTTYPE_CPM = 0x52; // CP/M; - // Microport System V/386 - public static final int PARTTYPE_ONTRACK_AUX = 0x53; // Ontrack ?; - public static final int PARTTYPE_ONTRACK = 0x54; // Ontrack ?; - public static final int PARTTYPE_EZ_DRIVE = 0x55; // EZ_DRIVE - public static final int PARTTYPE_VFEATURE = 0x56; // GoldenBow VFeature - public static final int PARTTYPE_PRIAM_EDISK = 0x5c; // Priam Edisk; - public static final int PARTTYPE_SPEEDSTOR = 0x61; // SpeedStor - public static final int PARTTYPE_UNIX_SYS_V = 0x63; // Unix SysV/386, 386/ix; - // ach, MtXinu BSD 4.3 on Mach; - // GNU HURD - public static final int PARTTYPE_NOVELL = 0x64; // Novell NetWare - public static final int PARTTYPE_NOVELL_31 = 0x65; // Novell NetWare (3.11) - public static final int PARTTYPE_DISK_SECURE = 0x70; // DiskSecure Multi-Boot - public static final int PARTTYPE_PC_IX = 0x75; // PC/IX - public static final int PARTTYPE_MINIX = 0x80; // Minix v1.1 - 1.4a - public static final int PARTTYPE_LINUX = 0x81; // Linux - // Mitac Advanced Disk Manager - public static final int PARTTYPE_LINUX_SWAP = 0x82; // Linux Swap partition - public static final int PARTTYPE_LINUXNATIVE = 0x83; // Linux native file system (ext2fs/xiafs) - public static final int PARTTYPE_OS2_HIDING_DOS = 0x84; // OS/2-renumbered type 04h partition (related to hiding DOS C: drive); - public static final int PARTTYPE_LINUX_EXTENDED = 0x85; // Linux extendet partition - public static final int PARTTYPE_LINUX_LVM = 0x8E; // Linux LVM - public static final int PARTTYPE_AMOEBA = 0x93; // Amoeba file system - public static final int PARTTYPE_AMOEBA_BAD_BLOCK = 0x94; // Amoeba bad block table - public static final int PARTTYPE_BSD = 0x9F; // BSD - public static final int PARTTYPE_THIK_PAD_HIDDEN = 0xA0; // IBM Thinkpad hidden partition - public static final int PARTTYPE_FREE_BSD = 0xA5; // FreeBSD - public static final int PARTTYPE_OPEN_BSD = 0xA6; // OpenBSD - public static final int PARTTYPE_NEXT_STEP = 0xA7; // NextStep - public static final int PARTTYPE_NETBSD = 0xA9; // NetBSD - public static final int PARTTYPE_BSDI = 0xB7; // BSDI file system (secondarily swap) - public static final int PARTTYPE_BSDI_SWAP = 0xB8; // BSDI swap partition (secondarily file system) - public static final int PARTTYPE_DR_DOS_12 = 0xC1; // DR-DOS 6.0 LOGIN.EXE-secured 12-bit FAT partition; - public static final int PARTTYPE_DR_DOS_16 = 0xC4; // DR-DOS 6.0 LOGIN.EXE-secured 16-bit FAT partition - public static final int PARTTYPE_DR_DOS_HUGE = 0xC6; // DR-DOS 6.0 LOGIN.EXE-secured Huge partition - public static final int PARTTYPE_CYRNIX = 0xC7; // Cyrnix Boot; - public static final int PARTTYPE_NON_FS = 0xDA; // Non FS Data; - public static final int PARTTYPE_CPM_DOS = 0xDB; // CP/M, Concurrent CP/M, Concurrent DOS - // CTOS (Convergent Technologies OS) - public static final int PARTTYPE_DELL_UTILITY = 0xDE; // DELL Utility partition - public static final int PARTTYPE_BOOT_IT = 0xDF; // Boot it - public static final int PARTTYPE_SPEEDSTOR_FAT_12 = 0xE1; // SpeedStor 12-bit FAT extended partition - public static final int PARTTYPE_DOS_R_O = 0xE3; // Readonly Dos Partition - public static final int PARTTYPE_SPEEDSTOR_FAT_16 = 0xE4; // SpeedStor 16-bit FAT extended partition - public static final int PARTTYPE_BEOS_FS = 0xEB; // BEO_FS - public static final int PARTTYPE_EFI_GPT = 0xEE; // EFI GPT - public static final int PARTTYPE_EFI_FAT = 0xEF; // BEO_FS - public static final int PARTTYPE_LINUX_PA_RISK = 0xF0; // Linux PA Risk - public static final int PARTTYPE_SPEEDSTORE_A = 0xF1; // Speedstore ??? - public static final int PARTTYPE_DOS3_3_SECENDORY = 0xF2; // DOS 3.3+ secondary - public static final int PARTTYPE_SPEEDSTORE_B = 0xF4; // Speedstore ??? - public static final int PARTTYPE_LINUX_RAID = 0xFD; // Linux Raid - public static final int PARTTYPE_LANSTEP = 0xFE; // LANstep - public static final int PARTTYPE_XENIX_BAD_BLOCK = 0xFF; // Xenix bad block table + public static IBMPartitionTypes valueOf(int code) { + for(IBMPartitionTypes type : IBMPartitionTypes.values()) + { + if(type.getCode() == code) + { + return type; + } + } + throw new IllegalArgumentException(code+" isn't a partition code"); + } + + private final int code; + private final String name; + private IBMPartitionTypes(int code, String name) { + this.code = code; + this.name = name; + } + + public int getCode() { + return code; + } + + public String getName() { + return name; + } + + public String toString() + { + return Integer.toHexString(code) + " - " + name; + } } Modified: trunk/fs/src/test/org/jnode/test/fs/filesystem/AbstractFSTest.java =================================================================== --- trunk/fs/src/test/org/jnode/test/fs/filesystem/AbstractFSTest.java 2007-02-11 22:12:18 UTC (rev 3116) +++ trunk/fs/src/test/org/jnode/test/fs/filesystem/AbstractFSTest.java 2007-02-11 22:19:06 UTC (rev 3117) @@ -55,7 +55,7 @@ private FileSystem fs; private FSTestConfig config; -// private Device device; + private Device device; public AbstractFSTest() { @@ -68,19 +68,21 @@ protected AbstractFSTest(String name) { super(name); -// this.fs = null; -// this.device = null; } final protected void setUp(FSTestConfig config) throws NameNotFoundException, FileSystemException, IOException, InstantiationException, IllegalAccessException, Exception { + super.setUp(); + this.config = config; - this.fs = config.getFileSystem().mount(config.getDeviceParam().getDevice()); + this.device = config.getDeviceParam().createDevice(); + this.fs = config.getFileSystem().mount(this.device); } final public void tearDown() throws E... [truncated message content] |
From: <fd...@us...> - 2007-02-11 22:12:21
|
Revision: 3116 http://jnode.svn.sourceforge.net/jnode/?rev=3116&view=rev Author: fduminy Date: 2007-02-11 14:12:18 -0800 (Sun, 11 Feb 2007) Log Message: ----------- for size computation : - created SizeUnit enum - added more units (that can fit in a long value) Modified Paths: -------------- trunk/core/src/core/org/jnode/util/NumberUtils.java Added Paths: ----------- trunk/core/src/core/org/jnode/util/SizeUnit.java Modified: trunk/core/src/core/org/jnode/util/NumberUtils.java =================================================================== --- trunk/core/src/core/org/jnode/util/NumberUtils.java 2007-02-10 21:22:09 UTC (rev 3115) +++ trunk/core/src/core/org/jnode/util/NumberUtils.java 2007-02-11 22:12:18 UTC (rev 3116) @@ -25,12 +25,6 @@ * @author epr */ public class NumberUtils { - - public static final int K = 1024; - public static final int M = 1024*1024; - public static final int G = 1024*1024*1024; - public static final long T = 1024l*1024l*1024l*1024l; - /** * Convert a float to a string with a given maximum number of fraction digits. * @param value @@ -219,61 +213,57 @@ * @return the text for of the size */ public static String size(long v) { - // Is < 1Kb? - if (v < K) { - return String.valueOf(v) + "B"; - } - // Is < 1Mb? - v = v >>> 10; - if (v < K) { - return String.valueOf(v) + "KB"; - } - // Is < 1Gb? - v = v >>> 10; - if (v < K) { - return String.valueOf(v) + "MB"; - } - // Is < 1Tb? - v = v >>> 10; - if (v < K) { - return String.valueOf(v) + "GB"; - } - // Large... - v = v >>> 10; - return String.valueOf(v) + "TB"; + SizeUnit prevUnit = SizeUnit.MIN; + for(SizeUnit unit : SizeUnit.values()) + { + if (v < unit.getMultiplier()) + { + return String.valueOf(v) + prevUnit.getUnit(); + } + v = v >>> 10; + prevUnit = unit; + } + return String.valueOf(v) + prevUnit.getUnit(); } /** * - * @param size a number eventually followed by a multiplier (K: Kilobytes, M: Megabytes, G:Gigabytes) + * @param size a number eventually followed by a multiplier (K: Kilobytes, M: Megabytes, G:Gigabytes, ...) * @return the numeric value of the size */ public static long getSize(String size) { if((size == null) || size.trim().equals("")) return 0; - - long multiplier = 1; - if(size.endsWith("B")) - size = size.substring(0, size.length() - 1); - - if(size.endsWith("T")) { - multiplier = T; - size = size.substring(0, size.length() - 1); - } else if(size.endsWith("G")) { - multiplier = G; - size = size.substring(0, size.length() - 1); - } else if(size.endsWith("M")) { - multiplier = M; - size = size.substring(0, size.length() - 1); - } else if(size.endsWith("K")) { - multiplier = K; - size = size.substring(0, size.length() - 1); + size = size.trim(); + long multiplier = SizeUnit.MIN.getMultiplier(); + SizeUnit sizeUnit = getSizeUnit(size); + if(sizeUnit != null) + { + multiplier = sizeUnit.getMultiplier(); + size = size.substring(0, size.length() - sizeUnit.getUnit().length()); } return Long.parseLong(size) * multiplier; } - + + public static SizeUnit getSizeUnit(String size) { + if((size == null) || size.trim().equals("")) + return null; + + size = size.trim(); + for(SizeUnit unit : SizeUnit.values()) + { + String unitStr = unit.getUnit(); + if(size.endsWith(unitStr)) + { + return unit; + } + } + + return null; + } + /** * This method avoids the use on Integer.toHexString, since this class may be used * during the boot-phase when the Integer class in not yet initialized. Added: trunk/core/src/core/org/jnode/util/SizeUnit.java =================================================================== --- trunk/core/src/core/org/jnode/util/SizeUnit.java (rev 0) +++ trunk/core/src/core/org/jnode/util/SizeUnit.java 2007-02-11 22:12:18 UTC (rev 3116) @@ -0,0 +1,39 @@ +package org.jnode.util; + +import java.math.BigInteger; + +public enum SizeUnit { + B(1l, "B"), + K(1024l, "K"), + M(1024l*1024l, "M"), + G(1024l*1024l*1024l, "G"), + T(1024l*1024l*1024l*1024l, "T"), + P(1024l*1024l*1024l*1024l*1024l, "P"), + E(1024l*1024l*1024l*1024l*1024l*1024l, "E"); + //these units have too big multipliers to fit in a long + // (aka they are greater than 2^64) : + //Z(1024l*1024l*1024l*1024l*1024l*1024l*1024l, "Z"), + //Y(1024l*1024l*1024l*1024l*1024l*1024l*1024l*1024l, "Y"); + + public static final SizeUnit MIN = B; + public static final SizeUnit MAX = E; + + final private long multiplier; + final private String unit; + + private SizeUnit(long multiplier, String unit) + { + this.multiplier = multiplier; + this.unit = unit; + } + + public long getMultiplier() { + return multiplier; + } + + public String getUnit() { + return unit; + } + + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-10 21:22:10
|
Revision: 3115 http://jnode.svn.sourceforge.net/jnode/?rev=3115&view=rev Author: lsantha Date: 2007-02-10 13:22:09 -0800 (Sat, 10 Feb 2007) Log Message: ----------- Updated to beanshell 2.0b4. Modified Paths: -------------- trunk/all/build.xml Modified: trunk/all/build.xml =================================================================== --- trunk/all/build.xml 2007-02-10 19:29:29 UTC (rev 3114) +++ trunk/all/build.xml 2007-02-10 21:22:09 UTC (rev 3115) @@ -63,7 +63,7 @@ <property name="gnu-crypto.jar" value="${root.dir}/core/lib/gnu-crypto.jar"/> <property name="javax-crypto.jar" value="${root.dir}/core/lib/javax-crypto.jar"/> <!-- property name="javax-security.jar" value="${root.dir}/core/lib/javax-security.jar" / --> - <property name="beanshell.jar" value="${root.dir}/shell/lib/bsh-2.0b1.jar"/> + <property name="beanshell.jar" value="${root.dir}/shell/lib/bsh-2.0b4.jar"/> <!-- libraries needed to check plugin dependencies --> <property name="bcel-5.1.jar" value="${root.dir}/builder/lib/bcel-5.1.jar" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-10 19:29:33
|
Revision: 3114 http://jnode.svn.sourceforge.net/jnode/?rev=3114&view=rev Author: lsantha Date: 2007-02-10 11:29:29 -0800 (Sat, 10 Feb 2007) Log Message: ----------- Removing the old beanshell. Removed Paths: ------------- trunk/shell/lib/bsh-2.0b1.jar Deleted: trunk/shell/lib/bsh-2.0b1.jar =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-10 19:23:33
|
Revision: 3113 http://jnode.svn.sourceforge.net/jnode/?rev=3113&view=rev Author: lsantha Date: 2007-02-10 11:23:31 -0800 (Sat, 10 Feb 2007) Log Message: ----------- Fixed bsh command and updated beanshell to 2.0b4. Modified Paths: -------------- trunk/shell/descriptors/org.jnode.shell.command.bsh.xml Added Paths: ----------- trunk/shell/lib/bsh-2.0b4.jar trunk/shell/src/shell/org/jnode/shell/command/bsh/BshCommand.java Removed Paths: ------------- trunk/shell/src/shell/org/jnode/shell/command/bsh/BeanshellCommand.java Modified: trunk/shell/descriptors/org.jnode.shell.command.bsh.xml =================================================================== --- trunk/shell/descriptors/org.jnode.shell.command.bsh.xml 2007-02-04 20:28:05 UTC (rev 3112) +++ trunk/shell/descriptors/org.jnode.shell.command.bsh.xml 2007-02-10 19:23:31 UTC (rev 3113) @@ -19,7 +19,7 @@ </runtime> <extension point="org.jnode.shell.aliases"> - <alias name="bsh" class="org.jnode.shell.command.bsh.BeanshellCommand"/> + <alias name="bsh" class="org.jnode.shell.command.bsh.BshCommand"/> </extension> <extension point="org.jnode.security.permissions"> Added: trunk/shell/lib/bsh-2.0b4.jar =================================================================== (Binary files differ) Property changes on: trunk/shell/lib/bsh-2.0b4.jar ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Deleted: trunk/shell/src/shell/org/jnode/shell/command/bsh/BeanshellCommand.java =================================================================== --- trunk/shell/src/shell/org/jnode/shell/command/bsh/BeanshellCommand.java 2007-02-04 20:28:05 UTC (rev 3112) +++ trunk/shell/src/shell/org/jnode/shell/command/bsh/BeanshellCommand.java 2007-02-10 19:23:31 UTC (rev 3113) @@ -1,235 +0,0 @@ -/* - * $Id$ - * - * JNode.org - * Copyright (C) 2003-2006 JNode.org - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; If not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -package org.jnode.shell.command.bsh; - -import gnu.java.io.NullOutputStream; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.io.Reader; -import java.io.StringReader; - -import bsh.ConsoleInterface; -import bsh.EvalError; -import bsh.Interpreter; - -/** - * User: Sam Reid Date: Jan 1, 2004 Time: 10:40:34 AM Copyright (c) Jan 1, 2004 - * by Sam Reid - */ -public class BeanshellCommand { - - private static Interpreter interpreter; - /*static { - //ConsoleInterface ci=new BshConsole(); - }*/ - - static class BshPrintStream extends PrintStream { - - public BshPrintStream() { - super(new NullOutputStream()); - } - - public void print(boolean b) { - // System.out.print - } - - public void print(char c) { - super.print(c); - } - - public void print(int i) { - super.print(i); - } - - public void print(long l) { - super.print(l); - } - - public void print(float f) { - super.print(f); - } - - public void print(double d) { - super.print(d); - } - - public void print(char[] s) { - super.print(s); - } - - public void print(String s) { - super.print(s); - } - - public void print(Object obj) { - super.print(obj); - } - - public void println() { - super.println(); - } - - public void println(boolean b) { - super.println(b); - } - - public void println(char c) { - super.println(c); - } - - public void println(int i) { - super.println(i); - } - - public void println(long l) { - super.println(l); - } - - public void println(float f) { - super.println(f); - } - - public void println(double d) { - super.println(d); - } - - public void println(char[] s) { - super.println(s); - } - - public void println(String s) { - super.println(s); - } - - public void println(Object obj) { - super.println(obj); - } - } - - static class BshConsole implements ConsoleInterface { - - StringReader in = new StringReader("234"); - - public Reader getIn() { - return in;//dummy - } - - public PrintStream getOut() { - return null; - } - - public PrintStream getErr() { - return null; - } - - public void println(Object o) { - } - - public void print(Object o) { - } - - public void error(Object o) { - } - - } - - /** - * Normal usage will be BeanshellCommand filename.bsh But you could also - * inline java code like this: BeanshellCommand -code "new - * JFrame().setVisible(true)"; <p/>BeanshellCommand should start an - * interactive session with beanshell. BeanshellCommand file.bsh should - * interpret and run the script. BeanshellCommand -code "code" should - * interpret and run the code. - */ - public static void showHelp() { - System.err - .println("Usage: \nbsh: interactive beanshell.\n" - + "bsh -help: this usage menu\n" - + "bsh -code CODE: evaluate the following shell code.\n" - + "bsh FILE: run the beanshell interpreter on the source FILE."); - } - - private static void evaluateFile(String arg) { - try { - System.err.println("Evaluating beanshell source=" + arg); - new Interpreter().source(arg); - } catch (IOException e) { - e.printStackTrace(); //To change body of catch statement use - // Options | File Templates. - } catch (EvalError evalError) { - evalError.printStackTrace(); //To change body of catch statement - // use Options | File Templates. - } - } - - public static void main(String[] args) { - // System.out.println("Started beanshell command."); - if (args.length == 0) { - //run interactive shell - // System.err.println("Interactive shell not yet written."); - runInteractiveShell(); - return; - } else if (args.length == 1 && args[ 0].toLowerCase().equals("-help")) { - System.err - .println("Usage: bsh: interactive beanshell. <not yet working>\n" - + "bsh FILE: run the beanshell interpreter on the source FILE. <not yet written>\n" - + "bsh -help: this usage menu\n" - + "bsh -code CODE: evaluate the following shell code."); - } else if (args.length == 1) { - evaluateFile(args[ 0]); - } else if (args.length == 2 && args[ 0].toLowerCase().equals("-code")) { - String sourcecode = args[ 1]; - evaluateSourceString(sourcecode); - } else if (args.length == 1 && args[ 0].toLowerCase().equals("-charva")) { - // runCharvaShell(); - } else { - showHelp(); - } - } - - private static void runInteractiveShell() { - System.err.println("Starting Interactive beanshell."); - Reader reader = new InputStreamReader(System.in); - Reader r2 = new BufferedReader(reader); - PrintStream out = new PrintStream(System.out); - PrintStream err = new PrintStream(System.err); - - Interpreter interpreter = new Interpreter(r2, out, err, true); - interpreter.run(); - System.err.println("Finished Interactive beanshell."); - } - - private static void evaluateSourceString(String sourcecode) { - System.out.println("Evaluating source string=" + sourcecode); - try { - Object out = interpreter.eval(sourcecode); - System.out.println(out); - } catch (EvalError evalError) { - evalError.printStackTrace(); //To change body of catch statement - // use Options | File Templates. - } - } - -} Copied: trunk/shell/src/shell/org/jnode/shell/command/bsh/BshCommand.java (from rev 3112, trunk/shell/src/shell/org/jnode/shell/command/bsh/BeanshellCommand.java) =================================================================== --- trunk/shell/src/shell/org/jnode/shell/command/bsh/BshCommand.java (rev 0) +++ trunk/shell/src/shell/org/jnode/shell/command/bsh/BshCommand.java 2007-02-10 19:23:31 UTC (rev 3113) @@ -0,0 +1,116 @@ +/* + * $Id$ + * + * JNode.org + * Copyright (C) 2003-2006 JNode.org + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.shell.command.bsh; + +import java.io.*; + +import bsh.Interpreter; +import org.jnode.shell.help.*; +import org.jnode.shell.help.argument.StringArgument; +import org.jnode.shell.help.argument.FileArgument; +import org.jnode.shell.help.argument.OptionArgument; +import org.jnode.shell.CommandLine; + +/** + * @author Levente S\u00e1ntha + */ +public class BshCommand { + + private static final StringArgument ARG_CODE = new StringArgument("code", "a BeanShell code snippet to execute"); + static final OptionArgument ARG_C = new OptionArgument("-c", "execute code", + new OptionArgument.Option("-c", "execute code")); + private static final Parameter PARAM_C = new Parameter(ARG_C, Parameter.MANDATORY); + private static final Parameter PARAM_CODE = new Parameter(ARG_CODE, Parameter.MANDATORY); + private static final FileArgument ARG_FILE = new FileArgument("file", "a BeanShell script file to execute"); + static final OptionArgument ARG_F = new OptionArgument("-f", "execute file", + new OptionArgument.Option("-f", "execute file")); + private static final Parameter PARAM_F = new Parameter(ARG_F, Parameter.MANDATORY); + private static final Parameter PARAM_FILE = new Parameter(ARG_FILE, Parameter.MANDATORY); + static final OptionArgument ARG_I = new OptionArgument("-i", "go interactive", + new OptionArgument.Option("-i", "go interactive")); + private static final Parameter PARAM_INTERACTIVE = new Parameter(ARG_I, Parameter.MANDATORY); + public static Help.Info HELP_INFO = new Help.Info( + "bsh", + new Syntax("start the interactive BeanShell interpreter"), + new Syntax("invoke the BeanShell interpreter", PARAM_C, PARAM_CODE), + new Syntax("invoke the BeanShell interpreter", PARAM_F, PARAM_FILE), + new Syntax("invoke the BeanShell interpreter", PARAM_C, PARAM_CODE, PARAM_F, PARAM_FILE), + new Syntax("invoke the BeanShell interpreter", PARAM_INTERACTIVE, PARAM_C, PARAM_CODE), + new Syntax("invoke the BeanShell interpreter", PARAM_INTERACTIVE, PARAM_F, PARAM_FILE), + new Syntax("invoke the BeanShell interpreter", PARAM_INTERACTIVE, PARAM_C, PARAM_CODE, PARAM_F, PARAM_FILE) + ); + + public static void main(String[] args) throws Exception { + new BshCommand().execute(new CommandLine(args), System.in, System.out, System.err); + } + + public void execute(CommandLine commandLine, InputStream in, PrintStream out, PrintStream err) throws Exception { + ParsedArguments parsedArguments = HELP_INFO.parse(commandLine.toStringArray()); + Interpreter bsh = null; + Object ret; + boolean interactive = false; + + if(PARAM_INTERACTIVE.isSet(parsedArguments)){ + bsh = createInterpreter(in, out, err, true); + interactive = true; + } + + + if (PARAM_C.isSet(parsedArguments)){ + if(bsh == null) + bsh = createInterpreter(in, out, err, false); + + String code = ARG_CODE.getValue(parsedArguments); + ret = bsh.eval(code); + + if(ret != null) + out.println(ret); + } + + + if(PARAM_F.isSet(parsedArguments)){ + if(bsh == null) + bsh = createInterpreter(in, out, err, false); + + String file = ARG_FILE.getValue(parsedArguments); + ret = bsh.source(file); + + if(ret != null) + out.println(ret); + } + + if(bsh == null){ + bsh = createInterpreter(in, out, err, true); + interactive = true; + } + + if(interactive) + bsh.run(); + } + + private static Interpreter createInterpreter(InputStream in, OutputStream out, OutputStream err, boolean interactive){ + return new Interpreter( + new BufferedReader(new InputStreamReader(in)), + new PrintStream(out), + new PrintStream(err), interactive); + } +} Property changes on: trunk/shell/src/shell/org/jnode/shell/command/bsh/BshCommand.java ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-04 20:28:15
|
Revision: 3112 http://jnode.svn.sourceforge.net/jnode/?rev=3112&view=rev Author: lsantha Date: 2007-02-04 12:28:05 -0800 (Sun, 04 Feb 2007) Log Message: ----------- Fixed overwritten text. (issue http://www.jnode.org/node/926) Modified Paths: -------------- trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsole.java Modified: trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsole.java =================================================================== --- trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsole.java 2007-02-04 16:03:05 UTC (rev 3111) +++ trunk/core/src/driver/org/jnode/driver/console/textscreen/TextScreenConsole.java 2007-02-04 20:28:05 UTC (rev 3112) @@ -124,6 +124,10 @@ if(ln > 0){ screen.set(screen.getOffset(curX, curY), v, offset + mark, ln, color); curX += ln; + if (curX >= scrWidth) { + curY++; + curX = curX - scrWidth; + } } mark = i + 1; putChar(c, color); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-04 16:03:08
|
Revision: 3111 http://jnode.svn.sourceforge.net/jnode/?rev=3111&view=rev Author: lsantha Date: 2007-02-04 08:03:05 -0800 (Sun, 04 Feb 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTabbedPaneUI.java Modified: trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTabbedPaneUI.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTabbedPaneUI.java 2007-02-04 16:01:44 UTC (rev 3110) +++ trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTabbedPaneUI.java 2007-02-04 16:03:05 UTC (rev 3111) @@ -902,6 +902,7 @@ default: tabAreaHeight = calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); + compX = insets.left + contentBorderInsets.left; compY = tabAreaHeight + insets.top + contentBorderInsets.top; } @@ -956,81 +957,50 @@ protected void normalizeTabRuns(int tabPlacement, int tabCount, int start, int max) { - if (tabPlacement == SwingUtilities.TOP - || tabPlacement == SwingUtilities.BOTTOM) + boolean horizontal = tabPlacement == TOP || tabPlacement == BOTTOM; + int currentRun = runCount - 1; + double weight = 1.25; + for (boolean adjust = true; adjust == true;) { - // We should only do this for runCount - 1, cause we can - // only shift that many times between runs. - for (int i = 1; i < runCount; i++) - { - Rectangle currRun = rects[lastTabInRun(tabCount, i)]; - Rectangle nextRun = rects[lastTabInRun(tabCount, - getNextTabRun(i))]; - int spaceInCurr = currRun.x + currRun.width; - int spaceInNext = nextRun.x + nextRun.width; - - int diffNow = spaceInCurr - spaceInNext; - int diffLater = (spaceInCurr - currRun.width) - - (spaceInNext + currRun.width); - - while (Math.abs(diffLater) < Math.abs(diffNow) - && spaceInNext + currRun.width < max) + int last = lastTabInRun(tabCount, currentRun); + int prevLast = lastTabInRun(tabCount, currentRun - 1); + int end; + int prevLength; + if (horizontal) { - tabRuns[i]--; - spaceInNext += currRun.width; - spaceInCurr -= currRun.width; - currRun = rects[lastTabInRun(tabCount, i)]; - diffNow = spaceInCurr - spaceInNext; - diffLater = (spaceInCurr - currRun.width) - - (spaceInNext + currRun.width); - } - - // Fixes the bounds of all tabs in the current - // run. - int first = tabRuns[i]; - int last = lastTabInRun(tabCount, i); - int currX = start; - for (int j = first; j <= last; j++) - { - rects[j].x = currX; - currX += rects[j].width; - } - } + end = rects[last].x + rects[last].width; + prevLength = (int) (maxTabWidth * weight); } else { - for (int i = 1; i < runCount; i++) + end = rects[last].y + rects[last].height; + prevLength = (int) (maxTabWidth * weight * 2); + } + if (max - end > prevLength) { - Rectangle currRun = rects[lastTabInRun(tabCount, i)]; - Rectangle nextRun = rects[lastTabInRun(tabCount, - getNextTabRun(i))]; - int spaceInCurr = currRun.y + currRun.height; - int spaceInNext = nextRun.y + nextRun.height; - - int diffNow = spaceInCurr - spaceInNext; - int diffLater = (spaceInCurr - currRun.height) - - (spaceInNext + currRun.height); - while (Math.abs(diffLater) < Math.abs(diffNow) - && spaceInNext + currRun.height < max) + tabRuns[currentRun] = prevLast; + if (horizontal) + rects[prevLast].x = start; + else + rects[prevLast].y = start; + for (int i = prevLast + 1; i <= last; i++) { - tabRuns[i]--; - spaceInNext += currRun.height; - spaceInCurr -= currRun.height; - currRun = rects[lastTabInRun(tabCount, i)]; - diffNow = spaceInCurr - spaceInNext; - diffLater = (spaceInCurr - currRun.height) - - (spaceInNext + currRun.height); + if (horizontal) + rects[i].x = rects[i - 1].x + rects[i - 1].width; + else + rects[i].y = rects[i - 1].y + rects[i - 1].height; } - - // Fixes the bounds of tabs in the current run. - int first = tabRuns[i]; - int last = lastTabInRun(tabCount, i); - int currY = start; - for (int j = first; j <= last; j++) - { - rects[j].y = currY; - currY += rects[j].height; } + else if (currentRun == runCount - 1) + adjust = false; + if (currentRun - 1 > 0) + currentRun -= 1; + else + { + // Check again, but with higher ratio to avoid + // clogging up the last run. + currentRun = runCount - 1; + weight += 0.25; } } } @@ -1394,7 +1364,7 @@ calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom; int height = 0; - int runHeight = tabAreaInsets.top + insets.top;; + int runHeight = tabAreaInsets.top + insets.top; int fontHeight = fm.getHeight(); int left = insets.left + tabAreaInsets.left; for (int i = 0; i < tabCount; i++) @@ -3528,7 +3498,8 @@ { Insets insets = getTabAreaInsets(tabPlacement); int tabAreaHeight = horizRunCount * maxTabHeight - - (horizRunCount - 1) * tabRunOverlay; + - (horizRunCount - 1) + * getTabRunOverlay(tabPlacement); tabAreaHeight += insets.top + insets.bottom; @@ -3550,7 +3521,8 @@ { Insets insets = getTabAreaInsets(tabPlacement); int tabAreaWidth = vertRunCount * maxTabWidth - - (vertRunCount - 1) * tabRunOverlay; + - (vertRunCount - 1) + * getTabRunOverlay(tabPlacement); tabAreaWidth += insets.left + insets.right; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-04 16:01:50
|
Revision: 3110 http://jnode.svn.sourceforge.net/jnode/?rev=3110&view=rev Author: lsantha Date: 2007-02-04 08:01:44 -0800 (Sun, 04 Feb 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicToolBarUI.java Modified: trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicToolBarUI.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicToolBarUI.java 2007-02-04 16:00:42 UTC (rev 3109) +++ trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicToolBarUI.java 2007-02-04 16:01:44 UTC (rev 3110) @@ -898,6 +898,7 @@ b.setRolloverEnabled(false); // Save old border in hashtable. + if (b.getBorder() != null) borders.put(b, b.getBorder()); b.setBorder(nonRolloverBorder); @@ -932,6 +933,7 @@ b.setRolloverEnabled(false); // Save old border in hashtable. + if (b.getBorder() != null) borders.put(b, b.getBorder()); b.setBorder(rolloverBorder); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-04 16:00:52
|
Revision: 3109 http://jnode.svn.sourceforge.net/jnode/?rev=3109&view=rev Author: lsantha Date: 2007-02-04 08:00:42 -0800 (Sun, 04 Feb 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTableUI.java trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTreeUI.java Modified: trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTableUI.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTableUI.java 2007-02-04 12:10:47 UTC (rev 3108) +++ trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTableUI.java 2007-02-04 16:00:42 UTC (rev 3109) @@ -443,11 +443,14 @@ public Dimension getPreferredSize(JComponent comp) { int prefTotalColumnWidth = 0; - for (int i = 0; i < table.getColumnCount(); i++) + TableColumnModel tcm = table.getColumnModel(); + + for (int i = 0; i < tcm.getColumnCount(); i++) { - TableColumn col = table.getColumnModel().getColumn(i); + TableColumn col = tcm.getColumn(i); prefTotalColumnWidth += col.getPreferredWidth(); } + return new Dimension(prefTotalColumnWidth, getHeight()); } Modified: trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTreeUI.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTreeUI.java 2007-02-04 12:10:47 UTC (rev 3108) +++ trunk/core/src/classpath/javax/javax/swing/plaf/basic/BasicTreeUI.java 2007-02-04 16:00:42 UTC (rev 3109) @@ -195,7 +195,7 @@ protected AbstractLayoutCache treeState; /** Used for minimizing the drawing of vertical lines. */ - protected Hashtable drawingCache; + protected Hashtable<TreePath, Boolean> drawingCache; /** * True if doing optimizations for a largeModel. Subclasses that don't support @@ -1587,12 +1587,15 @@ for (int i = startIndex; i <= endIndex; i++, k++) { path[k] = treeState.getPathForRow(i); + if (path[k] != null) + { isLeaf[k] = treeModel.isLeaf(path[k].getLastPathComponent()); isExpanded[k] = tree.isExpanded(path[k]); bounds[k] = getPathBounds(tree, path[k]); - paintHorizontalPartOfLeg(g, clip, insets, bounds[k], path[k], i, - isExpanded[k], false, isLeaf[k]); + paintHorizontalPartOfLeg(g, clip, insets, bounds[k], path[k], + i, isExpanded[k], false, isLeaf[k]); + } if (isLastChild(path[k])) paintVerticalPartOfLeg(g, clip, insets, path[k]); } @@ -1600,6 +1603,7 @@ k = 0; for (int i = startIndex; i <= endIndex; i++, k++) { + if (path[k] != null) paintRow(g, clip, insets, bounds[k], path[k], i, isExpanded[k], false, isLeaf[k]); } @@ -1611,7 +1615,9 @@ */ private boolean isLastChild(TreePath path) { - if (path instanceof GnuPath) + if (path == null) + return false; + else if (path instanceof GnuPath) { // Except the seldom case when the layout cache is changed, this // optimized code will be executed. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-04 12:10:50
|
Revision: 3108 http://jnode.svn.sourceforge.net/jnode/?rev=3108&view=rev Author: lsantha Date: 2007-02-04 04:10:47 -0800 (Sun, 04 Feb 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/javax/javax/swing/tree/AbstractLayoutCache.java trunk/core/src/classpath/javax/javax/swing/tree/DefaultMutableTreeNode.java trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeCellRenderer.java trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeModel.java trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeSelectionModel.java trunk/core/src/classpath/javax/javax/swing/tree/FixedHeightLayoutCache.java Modified: trunk/core/src/classpath/javax/javax/swing/tree/AbstractLayoutCache.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/tree/AbstractLayoutCache.java 2007-02-04 10:20:16 UTC (rev 3107) +++ trunk/core/src/classpath/javax/javax/swing/tree/AbstractLayoutCache.java 2007-02-04 12:10:47 UTC (rev 3108) @@ -149,9 +149,11 @@ protected Rectangle getNodeDimensions(Object value, int row, int depth, boolean expanded, Rectangle bounds) { - if (nodeDimensions == null) - throw new InternalError("The NodeDimensions are not set"); - return nodeDimensions.getNodeDimensions(value, row, depth, expanded, bounds); + Rectangle d = null; + if (nodeDimensions != null) + d = nodeDimensions.getNodeDimensions(value, row, depth, expanded, + bounds); + return d; } /** @@ -224,7 +226,12 @@ */ public void setSelectionModel(TreeSelectionModel model) { + if (treeSelectionModel != null) + treeSelectionModel.setRowMapper(null); treeSelectionModel = model; + if (treeSelectionModel != null) + treeSelectionModel.setRowMapper(this); + } /** @@ -337,7 +344,7 @@ * * @return Enumeration */ - public abstract Enumeration getVisiblePathsFrom(TreePath path); + public abstract Enumeration<TreePath> getVisiblePathsFrom(TreePath path); /** * getVisibleChildCount @@ -425,9 +432,13 @@ */ public int[] getRowsForPaths(TreePath[] paths) { - int[] rows = new int[paths.length]; + int[] rows = null; + if (paths != null) + { + rows = new int[paths.length]; for (int i = 0; i < rows.length; i++) rows[i] = getRowForPath(paths[i]); + } return rows; } @@ -440,6 +451,6 @@ */ protected boolean isFixedRowHeight() { - return false; + return rowHeight > 0; } } Modified: trunk/core/src/classpath/javax/javax/swing/tree/DefaultMutableTreeNode.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/tree/DefaultMutableTreeNode.java 2007-02-04 10:20:16 UTC (rev 3107) +++ trunk/core/src/classpath/javax/javax/swing/tree/DefaultMutableTreeNode.java 2007-02-04 12:10:47 UTC (rev 3108) @@ -67,7 +67,7 @@ * An empty enumeration, returned by {@link #children()} if a node has no * children. */ - public static final Enumeration EMPTY_ENUMERATION = + public static final Enumeration<TreeNode> EMPTY_ENUMERATION = EmptyEnumeration.getInstance(); /** @@ -78,7 +78,7 @@ /** * The child nodes for this node (may be empty). */ - protected Vector children = new Vector(); + protected Vector<MutableTreeNode> children = new Vector<MutableTreeNode>(); /** * userObject @@ -480,7 +480,7 @@ public TreeNode getSharedAncestor(DefaultMutableTreeNode node) { TreeNode current = this; - ArrayList list = new ArrayList(); + ArrayList<TreeNode> list = new ArrayList<TreeNode>(); while (current != null) { @@ -527,7 +527,7 @@ || children.size() == 0) return 0; - Stack stack = new Stack(); + Stack<Integer> stack = new Stack<Integer>(); stack.push(new Integer(0)); TreeNode node = getChildAt(0); int depth = 0; @@ -765,7 +765,7 @@ throw new IllegalArgumentException(); TreeNode parent = this; - Vector nodes = new Vector(); + Vector<TreeNode> nodes = new Vector<TreeNode>(); nodes.add(this); while (parent != node && parent != null) @@ -1148,7 +1148,7 @@ static class PostorderEnumeration implements Enumeration { - Stack nodes = new Stack(); + Stack<TreeNode> nodes = new Stack<TreeNode>(); Stack childrenEnums = new Stack(); PostorderEnumeration(TreeNode node) Modified: trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeCellRenderer.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeCellRenderer.java 2007-02-04 10:20:16 UTC (rev 3107) +++ trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeCellRenderer.java 2007-02-04 12:10:47 UTC (rev 3108) @@ -77,7 +77,7 @@ protected boolean hasFocus; /** - * drawsFocusBorderAroundIcon // FIXME: is this used? + * Indicates if the focus border is also drawn around the icon. */ private boolean drawsFocusBorderAroundIcon; @@ -152,6 +152,8 @@ setBackgroundNonSelectionColor(UIManager.getColor("Tree.textBackground")); setBackgroundSelectionColor(UIManager.getColor("Tree.selectionBackground")); setBorderSelectionColor(UIManager.getColor("Tree.selectionBorderColor")); + Object val = UIManager.get("Tree.drawsFocusBorderAroundIcon"); + drawsFocusBorderAroundIcon = val != null && ((Boolean) val).booleanValue(); } /** @@ -499,45 +501,63 @@ */ public void paint(Graphics g) { - // paint background - Rectangle vr = new Rectangle(); - Rectangle ir = new Rectangle(); - Rectangle tr = new Rectangle(); + // Determine background color. + Color bgColor; + if (selected) + bgColor = getBackgroundSelectionColor(); + else + { + bgColor = getBackgroundNonSelectionColor(); + if (bgColor == null) + bgColor = getBackground(); + } + // Paint background. + int xOffset = -1; + if (bgColor != null) + { + Icon i = getIcon(); + xOffset = getXOffset(); + g.setColor(bgColor); + g.fillRect(xOffset, 0, getWidth() - xOffset, getHeight()); + } - Insets insets = new Insets(0, 0, 0, 0); - Border border = UIManager.getBorder("Tree.selectionBorder"); - if (border != null) - insets = border.getBorderInsets(this); - - FontMetrics fm = getToolkit().getFontMetrics(getFont()); - SwingUtilities.layoutCompoundLabel((JLabel) this, fm, getText(), - getIcon(), getVerticalAlignment(), - getHorizontalAlignment(), - getVerticalTextPosition(), - getHorizontalTextPosition(), vr, ir, tr, - getIconTextGap()); - - // Reusing one rectangle. - Rectangle bounds = getBounds(ir); - - bounds.x = tr.x - insets.left; - bounds.width = tr.width + insets.left + insets.right; - - g.setColor(super.getBackground()); - g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); - + if (hasFocus) + { + if (drawsFocusBorderAroundIcon) + xOffset = 0; + else if (xOffset == -1) + xOffset = getXOffset(); + paintFocus(g, xOffset, 0, getWidth() - xOffset, getHeight()); + } super.paint(g); + } - // Paint the border of the focused element only (lead selection) - if (hasFocus) + /** + * Paints the focus indicator. + */ + private void paintFocus(Graphics g, int x, int y, int w, int h) { - Color b = getBorderSelectionColor(); - if (b != null) + Color col = getBorderSelectionColor(); + if (col != null) { - g.setColor(b); - g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height - 1); + g.setColor(col); + g.drawRect(x, y, w - 1, h - 1); } } + + /** + * Determines the X offset of the label that is caused by + * the icon. + * + * @return the X offset of the label + */ + private int getXOffset() + { + Icon i = getIcon(); + int offs = 0; + if (i != null && getText() != null) + offs = i.getIconWidth() + Math.max(0, getIconTextGap() - 1); + return offs; } /** Modified: trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeModel.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeModel.java 2007-02-04 10:20:16 UTC (rev 3107) +++ trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeModel.java 2007-02-04 12:10:47 UTC (rev 3108) @@ -210,17 +210,32 @@ } /** - * isLeaf + * Returns if the specified node is a leaf or not. When + * {@link #asksAllowsChildren} is true, then this checks if the TreeNode + * allows children, otherwise it returns the TreeNode's <code>leaf</code> + * property. * - * @param node TODO - * @return boolean + * @param node the node to check + * + * @return boolean <code>true</code> if the node is a leaf node, + * <code>false</code> otherwise + * + * @throws ClassCastException if the specified node is not a + * <code>TreeNode</code> instance + * + * @see TreeNode#getAllowsChildren() + * @see TreeNode#isLeaf() */ public boolean isLeaf(Object node) { - if (node instanceof TreeNode) - return ((TreeNode) node).isLeaf(); + // The RI throws a ClassCastException when node isn't a TreeNode, so do we. + TreeNode treeNode = (TreeNode) node; + boolean leaf; + if (asksAllowsChildren) + leaf = ! treeNode.getAllowsChildren(); else - return true; + leaf = treeNode.isLeaf(); + return leaf; } /** @@ -600,7 +615,7 @@ * * @since 1.3 */ - public EventListener[] getListeners(Class listenerType) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { return listenerList.getListeners(listenerType); } Modified: trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeSelectionModel.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeSelectionModel.java 2007-02-04 10:20:16 UTC (rev 3107) +++ trunk/core/src/classpath/javax/javax/swing/tree/DefaultTreeSelectionModel.java 2007-02-04 12:10:47 UTC (rev 3108) @@ -44,6 +44,7 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Arrays; +import java.util.BitSet; import java.util.EventListener; import java.util.HashSet; import java.util.Iterator; @@ -69,6 +70,38 @@ { /** + * According to the API docs, the method + * {@link DefaultTreeSelectionModel#notifyPathChange} should + * expect instances of a class PathPlaceHolder in the Vector parameter. + * This seems to be a non-public class, so I can only make guesses about the + * use of it. + */ + private static class PathPlaceHolder + { + /** + * The path that we wrap. + */ + TreePath path; + + /** + * Indicates if the path is new or already in the selection. + */ + boolean isNew; + + /** + * Creates a new instance. + * + * @param p the path to wrap + * @param n if the path is new or already in the selection + */ + PathPlaceHolder(TreePath p, boolean n) + { + path = p; + isNew = n; + } + } + + /** * Use serialVersionUID for interoperability. */ static final long serialVersionUID = 3288129636638950196L; @@ -124,12 +157,36 @@ protected int leadRow = -1; /** + * A supporting datastructure that is used in addSelectionPaths() and + * removeSelectionPaths(). It contains currently selected paths. + * + * @see #addSelectionPaths(TreePath[]) + * @see #removeSelectionPaths(TreePath[]) + * @see #setSelectionPaths(TreePath[]) + */ + private transient HashSet selectedPaths; + + /** + * A supporting datastructure that is used in addSelectionPaths() and + * removeSelectionPaths(). It contains the paths that are added or removed. + * + * @see #addSelectionPaths(TreePath[]) + * @see #removeSelectionPaths(TreePath[]) + * @see #setSelectionPaths(TreePath[]) + */ + private transient HashSet tmpPaths; + + /** * Constructs a new DefaultTreeSelectionModel. */ public DefaultTreeSelectionModel() { setSelectionMode(DISCONTIGUOUS_TREE_SELECTION); + listSelectionModel = new DefaultListSelectionModel(); listenerList = new EventListenerList(); + leadIndex = -1; + tmpPaths = new HashSet(); + selectedPaths = new HashSet(); } /** @@ -144,12 +201,14 @@ { DefaultTreeSelectionModel cloned = (DefaultTreeSelectionModel) super.clone(); - - // Clone the selection and the list selection model. + cloned.changeSupport = null; cloned.selection = (TreePath[]) selection.clone(); - if (listSelectionModel != null) - cloned.listSelectionModel - = (DefaultListSelectionModel) listSelectionModel.clone(); + cloned.listenerList = new EventListenerList(); + cloned.listSelectionModel = + (DefaultListSelectionModel) listSelectionModel.clone(); + cloned.selectedPaths = new HashSet(); + cloned.tmpPaths = new HashSet(); + return cloned; } @@ -209,6 +268,7 @@ public void setRowMapper(RowMapper mapper) { rowMapper = mapper; + resetRowSelection(); } /** @@ -236,8 +296,18 @@ */ public void setSelectionMode(int mode) { + int oldMode = selectionMode; selectionMode = mode; - insureRowContinuity(); + // Make sure we have a valid selection mode. + if (selectionMode != SINGLE_TREE_SELECTION + && selectionMode != CONTIGUOUS_TREE_SELECTION + && selectionMode != DISCONTIGUOUS_TREE_SELECTION) + selectionMode = DISCONTIGUOUS_TREE_SELECTION; + + // Fire property change event. + if (oldMode != selectionMode && changeSupport != null) + changeSupport.firePropertyChange(SELECTION_MODE_PROPERTY, oldMode, + selectionMode); } /** @@ -262,32 +332,10 @@ */ public void setSelectionPath(TreePath path) { - // The most frequently only one cell in the tree is selected. - TreePath[] ose = selection; - selection = new TreePath[] { path }; - TreePath oldLead = leadPath; - leadIndex = 0; - leadRow = getRow(path); - leadPath = path; - - TreeSelectionEvent event; - - if (ose != null && ose.length > 0) - { - // The first item in the path list is the selected path. - // The remaining items are unselected pathes. - TreePath[] changed = new TreePath[ose.length + 1]; - boolean[] news = new boolean[changed.length]; - news[0] = true; - changed[0] = path; - System.arraycopy(ose, 0, changed, 1, ose.length); - event = new TreeSelectionEvent(this, changed, news, oldLead, path); - } - else - { - event = new TreeSelectionEvent(this, path, true, oldLead, path); - } - fireValueChanged(event); + TreePath[] paths = null; + if (path != null) + paths = new TreePath[]{ path }; + setSelectionPaths(paths); } /** @@ -307,7 +355,7 @@ AbstractLayoutCache ama = (AbstractLayoutCache) mapper; return ama.getRowForPath(path); } - else + else if (mapper != null) { // Generic non optimized implementation. int[] rows = mapper.getRowsForPaths(new TreePath[] { path }); @@ -316,6 +364,7 @@ else return rows[0]; } + return -1; } /** @@ -327,10 +376,90 @@ */ public void setSelectionPaths(TreePath[] paths) { - // Must be called, as defined in JDK API 1.4. + int oldLength = 0; + if (selection != null) + oldLength = selection.length; + int newLength = 0; + if (paths != null) + newLength = paths.length; + if (newLength > 0 || oldLength > 0) + { + // For SINGLE_TREE_SELECTION and for CONTIGUOUS_TREE_SELECTION with + // a non-contiguous path, we only allow the first path element. + if ((selectionMode == SINGLE_TREE_SELECTION && newLength > 1) + || (selectionMode == CONTIGUOUS_TREE_SELECTION && newLength > 0 + && ! arePathsContiguous(paths))) + { + paths = new TreePath[] { paths[0] }; + newLength = 1; + } + // Find new paths. + Vector changedPaths = null; + tmpPaths.clear(); + int validPaths = 0; + TreePath oldLeadPath = leadPath; + for (int i = 0; i < newLength; i++) + { + if (paths[i] != null && ! tmpPaths.contains(paths[i])) + { + validPaths++; + tmpPaths.add(paths[i]); + if (! selectedPaths.contains(paths[i])) + { + if (changedPaths == null) + changedPaths = new Vector(); + changedPaths.add(new PathPlaceHolder(paths[i], true)); + } + leadPath = paths[i]; + } + } + // Put together the new selection. + TreePath[] newSelection = null; + if (validPaths != 0) + { + if (validPaths != newLength) + { + // Some of the paths are already selected, put together + // the new selection carefully. + newSelection = new TreePath[validPaths]; + Iterator newPaths = tmpPaths.iterator(); + validPaths = 0; + for (int i = 0; newPaths.hasNext(); i++) + newSelection[i] = (TreePath) newPaths.next(); + } + else + { + newSelection = new TreePath[paths.length]; + System.arraycopy(paths, 0, newSelection, 0, paths.length); + } + } + + // Find paths that have been selected, but are no more. + for (int i = 0; i < oldLength; i++) + { + if (selection[i] != null && ! tmpPaths.contains(selection[i])) + { + if (changedPaths == null) + changedPaths = new Vector(); + changedPaths.add(new PathPlaceHolder(selection[i], false)); + } + } + + // Perform changes and notification. + selection = newSelection; + HashSet tmp = selectedPaths; + selectedPaths = tmpPaths; + tmpPaths = tmp; + tmpPaths.clear(); + + // Not necessary, but required according to the specs and to tests. + if (selection != null) insureUniqueness(); - clearSelection(); - addSelectionPaths(paths); + updateLeadIndex(); + resetRowSelection(); + if (changedPaths != null && changedPaths.size() > 0) + notifyPathChange(changedPaths, oldLeadPath); + } } /** @@ -345,29 +474,10 @@ */ public void addSelectionPath(TreePath path) { - if (! isPathSelected(path)) - { - if (selectionMode == SINGLE_TREE_SELECTION || isSelectionEmpty() - || ! canPathBeAdded(path)) - setSelectionPath(path); - else - { - TreePath[] temp = new TreePath[selection.length + 1]; - System.arraycopy(selection, 0, temp, 0, selection.length); - temp[temp.length - 1] = path; - selection = new TreePath[temp.length]; - System.arraycopy(temp, 0, selection, 0, temp.length); - } - } - - if (path != leadPath) + if (path != null) { - TreePath oldLead = leadPath; - leadPath = path; - leadRow = getRow(path); - leadIndex = selection.length - 1; - fireValueChanged(new TreeSelectionEvent(this, path, true, oldLead, - leadPath)); + TreePath[] add = new TreePath[]{ path }; + addSelectionPaths(add); } } @@ -380,37 +490,76 @@ */ public void addSelectionPaths(TreePath[] paths) { - // Must be called, as defined in JDK API 1.4. - insureUniqueness(); - - if (paths != null) - { - TreePath v0 = null; - for (int i = 0; i < paths.length; i++) + int length = paths != null ? paths.length : 0; + if (length > 0) { - v0 = paths[i]; - if (! isPathSelected(v0)) + if (selectionMode == SINGLE_TREE_SELECTION) + setSelectionPaths(paths); + else if (selectionMode == CONTIGUOUS_TREE_SELECTION + && ! canPathsBeAdded(paths)) { - if (isSelectionEmpty()) - setSelectionPath(v0); + if (arePathsContiguous(paths)) + setSelectionPaths(paths); + else + setSelectionPaths(new TreePath[] { paths[0] }); + } else { - TreePath[] temp = new TreePath[selection.length + 1]; - System.arraycopy(selection, 0, temp, 0, selection.length); - temp[temp.length - 1] = v0; - selection = new TreePath[temp.length]; - System.arraycopy(temp, 0, selection, 0, temp.length); + Vector changedPaths = null; + tmpPaths.clear(); + int validPaths = 0; + TreePath oldLeadPath = leadPath; + int oldPaths = 0; + if (selection != null) + oldPaths = selection.length; + int i; + for (i = 0; i < length; i++) + { + if (paths[i] != null) + { + if (! selectedPaths.contains(paths[i])) + { + validPaths++; + if (changedPaths == null) + changedPaths = new Vector(); + changedPaths.add(new PathPlaceHolder(paths[i], true)); + selectedPaths.add(paths[i]); + tmpPaths.add(paths[i]); } - TreePath oldLead = leadPath; - leadPath = paths[paths.length - 1]; - leadRow = getRow(leadPath); - leadIndex = selection.length - 1; - - fireValueChanged(new TreeSelectionEvent(this, v0, true, - oldLead, leadPath)); + leadPath = paths[i]; } } - insureRowContinuity(); + if (validPaths > 0) + { + TreePath[] newSelection = new TreePath[oldPaths + validPaths]; + if (oldPaths > 0) + System.arraycopy(selection, 0, newSelection, 0, oldPaths); + if (validPaths != paths.length) + { + // Some of the paths are already selected, put together + // the new selection carefully. + Iterator newPaths = tmpPaths.iterator(); + i = oldPaths; + while (newPaths.hasNext()) + { + newSelection[i] = (TreePath) newPaths.next(); + i++; + } + } + else + System.arraycopy(paths, 0, newSelection, oldPaths, + validPaths); + selection = newSelection; + insureUniqueness(); + updateLeadIndex(); + resetRowSelection(); + if (changedPaths != null && changedPaths.size() > 0) + notifyPathChange(changedPaths, oldLeadPath); + } + else + leadPath = oldLeadPath; + tmpPaths.clear(); + } } } @@ -422,36 +571,8 @@ */ public void removeSelectionPath(TreePath path) { - if (isSelectionEmpty()) - return; - - int index = - 1; - if (isPathSelected(path)) - { - for (int i = 0; i < selection.length; i++) - { - if (selection[i].equals(path)) - { - index = i; - break; - } - } - TreePath[] temp = new TreePath[selection.length - 1]; - System.arraycopy(selection, 0, temp, 0, index); - System.arraycopy(selection, index + 1, temp, index, selection.length - - index - 1); - selection = new TreePath[temp.length]; - System.arraycopy(temp, 0, selection, 0, temp.length); - - // If the removed path was the lead path, set the lead path to null. - TreePath oldLead = leadPath; - if (path != null && leadPath != null && path.equals(leadPath)) - leadPath = null; - - fireValueChanged(new TreeSelectionEvent(this, path, false, oldLead, - leadPath)); - insureRowContinuity(); - } + if (path != null) + removeSelectionPaths(new TreePath[]{ path }); } /** @@ -462,40 +583,54 @@ */ public void removeSelectionPaths(TreePath[] paths) { - if (isSelectionEmpty()) - return; - if (paths != null) + if (paths != null && selection != null && paths.length > 0) { - int index = - 1; - TreePath v0 = null; - TreePath oldLead = leadPath; - for (int i = 0; i < paths.length; i++) + if (! canPathsBeRemoved(paths)) + clearSelection(); + else + { + Vector pathsToRemove = null; + for (int i = paths.length - 1; i >= 0; i--) { - v0 = paths[i]; - if (isPathSelected(v0)) + if (paths[i] != null && selectedPaths.contains(paths[i])) { - for (int x = 0; x < selection.length; x++) + if (pathsToRemove == null) + pathsToRemove = new Vector(); + selectedPaths.remove(paths[i]); + pathsToRemove.add(new PathPlaceHolder(paths[i], + false)); + } + } + if (pathsToRemove != null) { - if (selection[i].equals(v0)) + int numRemove = pathsToRemove.size(); + TreePath oldLead = leadPath; + if (numRemove == selection.length) + selection = null; + else { - index = x; - break; + selection = new TreePath[selection.length - numRemove]; + Iterator keep = selectedPaths.iterator(); + for (int valid = 0; keep.hasNext(); valid++) + selection[valid] = (TreePath) keep.next(); } - if (leadPath != null && leadPath.equals(v0)) + // Update lead path. + if (leadPath != null && ! selectedPaths.contains(leadPath)) + { + if (selection != null) + leadPath = selection[selection.length - 1]; + else leadPath = null; } - TreePath[] temp = new TreePath[selection.length - 1]; - System.arraycopy(selection, 0, temp, 0, index); - System.arraycopy(selection, index + 1, temp, index, - selection.length - index - 1); - selection = new TreePath[temp.length]; - System.arraycopy(temp, 0, selection, 0, temp.length); - - fireValueChanged(new TreeSelectionEvent(this, v0, false, - oldLead, leadPath)); + else if (selection != null) + leadPath = selection[selection.length - 1]; + else + leadPath = null; + updateLeadIndex(); + resetRowSelection(); + notifyPathChange(pathsToRemove, oldLead); } } - insureRowContinuity(); } } @@ -572,20 +707,23 @@ */ public void clearSelection() { - if (! isSelectionEmpty()) + if (selection != null) { - TreeSelectionEvent event = new TreeSelectionEvent( - this, selection, new boolean[selection.length], leadPath, null); + int selectionLength = selection.length; + boolean[] news = new boolean[selectionLength]; + Arrays.fill(news, false); + TreeSelectionEvent event = new TreeSelectionEvent(this, selection, + news, leadPath, + null); leadPath = null; + leadIndex = 0; + leadRow = 0; + selectedPaths.clear(); selection = null; + resetRowSelection(); fireValueChanged(event); } - else - { - leadPath = null; - selection = null; } - } /** * Adds a <code>TreeSelectionListener</code> object to this model. @@ -638,7 +776,7 @@ * @return an array of listeners * @since 1.3 */ - public EventListener[] getListeners(Class listenerType) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { return listenerList.getListeners(listenerType); } @@ -650,10 +788,43 @@ */ public int[] getSelectionRows() { - if (rowMapper == null) - return null; + int[] rows = null; + if (rowMapper != null && selection != null) + { + rows = rowMapper.getRowsForPaths(selection); + if (rows != null) + { + // Find invisible rows. + int invisible = 0; + for (int i = rows.length - 1; i >= 0; i--) + { + if (rows[i] == -1) + invisible++; + + } + // Clean up invisible rows. + if (invisible > 0) + { + if (invisible == rows.length) + rows = null; else - return rowMapper.getRowsForPaths(selection); + { + int[] newRows = new int[rows.length - invisible]; + int visCount = 0; + for (int i = rows.length - 1; i >= 0; i--) + { + if (rows[i] != -1) + { + newRows[visCount] = rows[i]; + visCount++; + } + } + rows = newRows; + } + } + } + } + return rows; } /** @@ -663,16 +834,7 @@ */ public int getMinSelectionRow() { - if ((rowMapper == null) || (selection == null) || (selection.length == 0)) - return - 1; - else - { - int[] rows = rowMapper.getRowsForPaths(selection); - int minRow = Integer.MAX_VALUE; - for (int index = 0; index < rows.length; index++) - minRow = Math.min(minRow, rows[index]); - return minRow; - } + return listSelectionModel.getMinSelectionIndex(); } /** @@ -682,16 +844,7 @@ */ public int getMaxSelectionRow() { - if ((rowMapper == null) || (selection == null) || (selection.length == 0)) - return - 1; - else - { - int[] rows = rowMapper.getRowsForPaths(selection); - int maxRow = - 1; - for (int index = 0; index < rows.length; index++) - maxRow = Math.max(maxRow, rows[index]); - return maxRow; - } + return listSelectionModel.getMaxSelectionIndex(); } /** @@ -706,29 +859,7 @@ */ public boolean isRowSelected(int row) { - // Return false if nothing is selected. - if (isSelectionEmpty()) - return false; - - RowMapper mapper = getRowMapper(); - - if (mapper instanceof AbstractLayoutCache) - { - // The absolute majority of cases, unless the TreeUI is very - // seriously rewritten - AbstractLayoutCache ama = (AbstractLayoutCache) mapper; - TreePath path = ama.getPathForRow(row); - return isPathSelected(path); - } - else - { - // Generic non optimized implementation. - int[] rows = mapper.getRowsForPaths(selection); - for (int i = 0; i < rows.length; i++) - if (rows[i] == row) - return true; - return false; - } + return listSelectionModel.isSelectedIndex(row); } /** @@ -736,7 +867,32 @@ */ public void resetRowSelection() { - // Nothing to do here. + listSelectionModel.clearSelection(); + if (selection != null && rowMapper != null) + { + int[] rows = rowMapper.getRowsForPaths(selection); + // Update list selection model. + for (int i = 0; i < rows.length; i++) + { + int row = rows[i]; + if (row != -1) + listSelectionModel.addSelectionInterval(row, row); + } + // Update lead selection. + if (leadIndex != -1 && rows != null) + leadRow = rows[leadIndex]; + else if (leadPath != null) + { + TreePath[] tmp = new TreePath[]{ leadPath }; + rows = rowMapper.getRowsForPaths(tmp); + leadRow = rows != null ? rows[0] : -1; + } + else + leadRow = -1; + insureRowContinuity(); + } + else + leadRow = -1; } /** @@ -766,6 +922,8 @@ */ public void addPropertyChangeListener(PropertyChangeListener listener) { + if (changeSupport == null) + changeSupport = new SwingPropertyChangeSupport(this); changeSupport.addPropertyChangeListener(listener); } @@ -776,6 +934,7 @@ */ public void removePropertyChangeListener(PropertyChangeListener listener) { + if (changeSupport != null) changeSupport.removePropertyChangeListener(listener); } @@ -787,7 +946,12 @@ */ public PropertyChangeListener[] getPropertyChangeListeners() { - return changeSupport.getPropertyChangeListeners(); + PropertyChangeListener[] listeners = null; + if (changeSupport != null) + listeners = changeSupport.getPropertyChangeListeners(); + else + listeners = new PropertyChangeListener[0]; + return listeners; } /** @@ -801,65 +965,39 @@ */ protected void insureRowContinuity() { - if (selection == null || selection.length < 2) - return; - else if (selectionMode == CONTIGUOUS_TREE_SELECTION) + if (selectionMode == CONTIGUOUS_TREE_SELECTION && selection != null + && rowMapper != null) { - if (rowMapper == null) - // This is the best we can do without the row mapper: - selectOne(); + int min = listSelectionModel.getMinSelectionIndex(); + if (min != -1) + { + int max = listSelectionModel.getMaxSelectionIndex(); + for (int i = min; i <= max; i++) + { + if (! listSelectionModel.isSelectedIndex(i)) + { + if (i == min) + clearSelection(); else { + TreePath[] newSelection = new TreePath[i - min]; int[] rows = rowMapper.getRowsForPaths(selection); - Arrays.sort(rows); - int i; - for (i = 1; i < rows.length; i++) + for (int j = 0; j < rows.length; j++) { - if (rows[i - 1] != rows[i] - 1) - // Break if no longer continuous. + if (rows[j] < i) + newSelection[rows[j] - min] = selection[j]; + } + setSelectionPaths(newSelection); break; } - - if (i < rows.length) - { - TreePath[] ns = new TreePath[i]; - for (int j = 0; j < ns.length; j++) - ns[i] = getPath(j); - setSelectionPaths(ns); } } } - else if (selectionMode == SINGLE_TREE_SELECTION) - selectOne(); } - - /** - * Keep only one (normally last or leading) path in the selection. - */ - private void selectOne() - { - if (leadIndex > 0 && leadIndex < selection.length) - setSelectionPath(selection[leadIndex]); - else - setSelectionPath(selection[selection.length - 1]); + else if (selectionMode == SINGLE_TREE_SELECTION && selection != null + && selection.length > 1) + setSelectionPath(selection[0]); } - - /** - * Get path for the given row that must be in the current selection. - */ - private TreePath getPath(int row) - { - if (rowMapper instanceof AbstractLayoutCache) - return ((AbstractLayoutCache) rowMapper).getPathForRow(row); - else - { - int[] rows = rowMapper.getRowsForPaths(selection); - for (int i = 0; i < rows.length; i++) - if (rows[i] == row) - return selection[i]; - } - throw new InternalError(row + " not in selection"); - } /** * Returns <code>true</code> if the paths are contiguous (take subsequent @@ -875,16 +1013,36 @@ if (rowMapper == null || paths.length < 2) return true; - int[] rows = rowMapper.getRowsForPaths(paths); - - // The patches may not be sorted. - Arrays.sort(rows); + int length = paths.length; + TreePath[] tmp = new TreePath[1]; + tmp[0] = paths[0]; + int min = rowMapper.getRowsForPaths(tmp)[0]; + BitSet selected = new BitSet(); + int valid = 0; + for (int i = 0; i < length; i++) + { + if (paths[i] != null) + { + tmp[0] = paths[i]; + int[] rows = rowMapper.getRowsForPaths(tmp); + if (rows == null) + return false; // No row mapping yet, can't be selected. + int row = rows[0]; + if (row == -1 || row < (min - length) || row > (min + length)) + return false; // Not contiguous. + min = Math.min(min, row); + if (! selected.get(row)) + { + selected.set(row); + valid++; + } - for (int i = 1; i < rows.length; i++) - { - if (rows[i - 1] != rows[i] - 1) - return false; } + } + int max = valid + min; + for (int i = min; i < max; i++) + if (! selected.get(i)) + return false; // Not contiguous. return true; } @@ -904,31 +1062,48 @@ */ protected boolean canPathsBeAdded(TreePath[] paths) { - if (rowMapper == null || isSelectionEmpty() - || selectionMode == DISCONTIGUOUS_TREE_SELECTION) + if (paths == null || paths.length == 0 || rowMapper == null + || selection == null || selectionMode == DISCONTIGUOUS_TREE_SELECTION) return true; - TreePath [] all = new TreePath[paths.length + selection.length]; - System.arraycopy(paths, 0, all, 0, paths.length); - System.arraycopy(selection, 0, all, paths.length, selection.length); - - return arePathsContiguous(all); + BitSet selected = new BitSet(); + int min = listSelectionModel.getMinSelectionIndex(); + int max = listSelectionModel.getMaxSelectionIndex(); + TreePath[] tmp = new TreePath[1]; + if (min != -1) + { + // Set the bitmask of selected elements. + for (int i = min; i <= max; i++) + selected.set(i); } - - /** - * Checks if the single path can be added to selection. - */ - private boolean canPathBeAdded(TreePath path) + else { - if (rowMapper == null || isSelectionEmpty() - || selectionMode == DISCONTIGUOUS_TREE_SELECTION) + tmp[0] = paths[0]; + min = rowMapper.getRowsForPaths(tmp)[0]; + max = min; + } + // Mark new paths as selected. + for (int i = paths.length - 1; i >= 0; i--) + { + if (paths[i] != null) + { + tmp[0] = paths[i]; + int[] rows = rowMapper.getRowsForPaths(tmp); + if (rows == null) + return false; // Now row mapping yet, can't be selected. + int row = rows[0]; + if (row == -1) + return false; // Now row mapping yet, can't be selected. + min = Math.min(min, row); + max = Math.max(max, row); + selected.set(row); + } + } + // Now look if the new selection would be contiguous. + for (int i = min; i <= max; i++) + if (! selected.get(i)) + return false; return true; - - TreePath[] all = new TreePath[selection.length + 1]; - System.arraycopy(selection, 0, all, 0, selection.length); - all[all.length - 1] = path; - - return arePathsContiguous(all); } /** @@ -966,20 +1141,23 @@ * method will call listeners if invoked, but it is not called from the * implementation of this class. * - * @param vPathes the vector of the changed patches + * @param vPaths the vector of the changed patches * @param oldLeadSelection the old selection index */ - protected void notifyPathChange(Vector vPathes, TreePath oldLeadSelection) + protected void notifyPathChange(Vector vPaths, TreePath oldLeadSelection) { - TreePath[] pathes = new TreePath[vPathes.size()]; - for (int i = 0; i < pathes.length; i++) - pathes[i] = (TreePath) vPathes.get(i); - boolean[] news = new boolean[pathes.length]; - for (int i = 0; i < news.length; i++) - news[i] = isPathSelected(pathes[i]); + int numChangedPaths = vPaths.size(); + boolean[] news = new boolean[numChangedPaths]; + TreePath[] paths = new TreePath[numChangedPaths]; + for (int i = 0; i < numChangedPaths; i++) + { + PathPlaceHolder p = (PathPlaceHolder) vPaths.get(i); + news[i] = p.isNew; + paths[i] = p.path; + } - TreeSelectionEvent event = new TreeSelectionEvent(this, pathes, news, + TreeSelectionEvent event = new TreeSelectionEvent(this, paths, news, oldLeadSelection, leadPath); fireValueChanged(event); @@ -991,22 +1169,20 @@ */ protected void updateLeadIndex() { - if (isSelectionEmpty()) + leadIndex = -1; + if (leadPath != null) { - leadRow = leadIndex = - 1; - } + leadRow = -1; + if (selection == null) + leadPath = null; else { - leadRow = getRow(leadPath); - for (int i = 0; i < selection.length; i++) - { - if (selection[i].equals(leadPath)) + for (int i = selection.length - 1; i >= 0 && leadIndex == -1; i--) { + if (selection[i] == leadPath) leadIndex = i; - break; } } - leadIndex = leadRow; } } Modified: trunk/core/src/classpath/javax/javax/swing/tree/FixedHeightLayoutCache.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/tree/FixedHeightLayoutCache.java 2007-02-04 10:20:16 UTC (rev 3107) +++ trunk/core/src/classpath/javax/javax/swing/tree/FixedHeightLayoutCache.java 2007-02-04 12:10:47 UTC (rev 3108) @@ -480,7 +480,7 @@ * @param parentPath the parent path * @return the enumeration over pathes */ - public Enumeration getVisiblePathsFrom(TreePath parentPath) + public Enumeration<TreePath> getVisiblePathsFrom(TreePath parentPath) { if (dirty) update(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-04 10:20:21
|
Revision: 3107 http://jnode.svn.sourceforge.net/jnode/?rev=3107&view=rev Author: lsantha Date: 2007-02-04 02:20:16 -0800 (Sun, 04 Feb 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/javax/javax/swing/plaf/metal/DefaultMetalTheme.java trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalCheckBoxIcon.java trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalComboBoxUI.java trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalFileChooserUI.java trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalIconFactory.java trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalRadioButtonUI.java trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalScrollBarUI.java trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalSliderUI.java trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalUtils.java Modified: trunk/core/src/classpath/javax/javax/swing/plaf/metal/DefaultMetalTheme.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/metal/DefaultMetalTheme.java 2007-02-04 09:46:03 UTC (rev 3106) +++ trunk/core/src/classpath/javax/javax/swing/plaf/metal/DefaultMetalTheme.java 2007-02-04 10:20:16 UTC (rev 3107) @@ -38,8 +38,11 @@ package javax.swing.plaf.metal; +import gnu.classpath.SystemProperties; + import java.awt.Font; +import javax.swing.UIManager; import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.FontUIResource; @@ -63,10 +66,6 @@ private static final ColorUIResource SECONDARY3 = new ColorUIResource(204, 204, 204); - private static final FontUIResource CONTROL_TEXT_FONT = - new FontUIResource("Dialog", Font.BOLD, 12); - private static final FontUIResource MENU_TEXT_FONT = - new FontUIResource("Dialog", Font.BOLD, 12); private static final FontUIResource SUB_TEXT_FONT = new FontUIResource("Dialog", Font.PLAIN, 10); private static final FontUIResource SYSTEM_TEXT_FONT = @@ -77,6 +76,40 @@ new FontUIResource("Dialog", Font.BOLD, 12); /** + * The control text font for swing.boldMetal=false. + */ + private static final FontUIResource PLAIN_CONTROL_TEXT_FONT = + new FontUIResource("Dialog", Font.PLAIN, 12); + + /** + * The standard control text font. + */ + private static final FontUIResource BOLD_CONTROL_TEXT_FONT = + new FontUIResource("Dialog", Font.BOLD, 12); + + /** + * The menu text font for swing.boldMetal=false. + */ + private static final FontUIResource PLAIN_MENU_TEXT_FONT = + new FontUIResource("Dialog", Font.PLAIN, 12); + + /** + * The menu control text font. + */ + private static final FontUIResource BOLD_MENU_TEXT_FONT = + new FontUIResource("Dialog", Font.BOLD, 12); + + /** + * Indicates the control text font. + */ + static final int CONTROL_TEXT_FONT = 1; + + /** + * Indicates the menu text font. + */ + static final int MENU_TEXT_FONT = 2; + + /** * Creates a new instance of this theme. */ public DefaultMetalTheme() @@ -156,23 +189,28 @@ /** * Returns the font used for text on controls. In this case, the font is - * <code>FontUIResource("Dialog", Font.BOLD, 12)</code>. + * <code>FontUIResource("Dialog", Font.BOLD, 12)</code>, unless the + * <code>swing.boldMetal</code> UI default is set to {@link Boolean#FALSE} + * in which case it is <code>FontUIResource("Dialog", Font.PLAIN, 12)</code>. * * @return The font. */ public FontUIResource getControlTextFont() { - return CONTROL_TEXT_FONT; + return getFont(CONTROL_TEXT_FONT); } + /** * Returns the font used for text in menus. In this case, the font is - * <code>FontUIResource("Dialog", Font.BOLD, 12)</code>. + * <code>FontUIResource("Dialog", Font.BOLD, 12)</code>, unless the + * <code>swing.boldMetal</code> UI default is set to {@link Boolean#FALSE} + * in which case it is <code>FontUIResource("Dialog", Font.PLAIN, 12)</code>. * * @return The font used for text in menus. */ public FontUIResource getMenuTextFont() { - return MENU_TEXT_FONT; + return getFont(MENU_TEXT_FONT); } /** @@ -218,4 +256,50 @@ { return WINDOW_TITLE_FONT; } + + /** + * Returns the appropriate font. The font type to return is identified + * by the specified id. + * + * @param id the font type to return + * + * @return the correct font + */ + private FontUIResource getFont(int id) + { + FontUIResource font = null; + switch (id) + { + case CONTROL_TEXT_FONT: + if (isBoldMetal()) + font = BOLD_CONTROL_TEXT_FONT; + else + font = PLAIN_CONTROL_TEXT_FONT; + break; + case MENU_TEXT_FONT: + if (isBoldMetal()) + font = BOLD_MENU_TEXT_FONT; + else + font = PLAIN_MENU_TEXT_FONT; + break; + // TODO: Add other font types and their mapping here. + } + return font; + } + + /** + * Determines if the theme should be bold or not. The theme is bold by + * default, this can be turned off by setting the system property + * swing.boldMetal to true, or by putting the property with the same name + * into the current UIManager's defaults. + * + * @return <code>true</code>, when the theme is bold, <code>false</code> + * otherwise + */ + private boolean isBoldMetal() + { + Object boldMetal = UIManager.get("swing.boldMetal"); + return (boldMetal == null || ! Boolean.FALSE.equals(boldMetal)) + && ! ("false".equals(SystemProperties.getProperty("swing.boldMetal"))); + } } Modified: trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalCheckBoxIcon.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalCheckBoxIcon.java 2007-02-04 09:46:03 UTC (rev 3106) +++ trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalCheckBoxIcon.java 2007-02-04 10:20:16 UTC (rev 3107) @@ -1,5 +1,5 @@ /* MetalCheckBoxIcon.java -- An icon for JCheckBoxes in the Metal L&F - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,8 +42,8 @@ import java.awt.Graphics; import java.io.Serializable; +import javax.swing.AbstractButton; import javax.swing.Icon; -import javax.swing.JCheckBox; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.plaf.UIResource; @@ -134,8 +134,9 @@ MetalUtils.paintGradient(g, x, y, getIconWidth(), getIconHeight(), SwingConstants.VERTICAL, "CheckBox.gradient"); border.paintBorder(c, g, x, y, getIconWidth(), getIconHeight()); - JCheckBox cb = (JCheckBox) c; - if (cb.isSelected()) - drawCheck(c, g, x, y); + + AbstractButton b = (AbstractButton) c; + if (b.isSelected()) + drawCheck(b, g, x, y); } } Modified: trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalComboBoxUI.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalComboBoxUI.java 2007-02-04 09:46:03 UTC (rev 3106) +++ trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalComboBoxUI.java 2007-02-04 10:20:16 UTC (rev 3107) @@ -48,7 +48,6 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import javax.swing.CellRendererPane; import javax.swing.ComboBoxEditor; import javax.swing.Icon; import javax.swing.JButton; @@ -217,7 +216,7 @@ */ protected ComboPopup createPopup() { - return new MetalComboPopup(comboBox); + return super.createPopup(); } /** @@ -228,7 +227,7 @@ protected JButton createArrowButton() { JButton button = new MetalComboBoxButton(comboBox, new MetalComboBoxIcon(), - new CellRendererPane(), listBox); + currentValuePane, listBox); button.setMargin(new Insets(0, 1, 1, 3)); return button; } @@ -305,7 +304,6 @@ { MetalComboBoxButton b = (MetalComboBoxButton) arrowButton; d = getDisplaySize(); - Insets insets = b.getInsets(); Insets arrowInsets = b.getInsets(); Insets comboInsets = comboBox.getInsets(); Icon icon = b.getComboIcon(); Modified: trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalFileChooserUI.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalFileChooserUI.java 2007-02-04 09:46:03 UTC (rev 3106) +++ trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalFileChooserUI.java 2007-02-04 10:20:16 UTC (rev 3107) @@ -42,6 +42,7 @@ import java.awt.Component; import java.awt.Container; import java.awt.Dimension; +import java.awt.Graphics; import java.awt.GridLayout; import java.awt.Insets; import java.awt.LayoutManager; @@ -55,7 +56,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; -import java.util.Date; +import java.sql.Date; import java.text.DateFormat; import java.text.NumberFormat; import java.util.List; @@ -303,7 +304,8 @@ if (file == null) setFileName(null); - else + else if (file.isFile() || filechooser.getFileSelectionMode() + != JFileChooser.FILES_ONLY) setFileName(file.getName()); int index = -1; index = getModel().indexOf(file); @@ -439,7 +441,7 @@ filechooser.revalidate(); filechooser.repaint(); } - }; + } /** * A combo box model containing the selected directory and all its parent @@ -567,10 +569,17 @@ extends DefaultListCellRenderer { /** + * This is the icon that is displayed in the combobox. This wraps + * the standard icon and adds indendation. + */ + private IndentIcon indentIcon; + + /** * Creates a new renderer. */ public DirectoryComboBoxRenderer(JFileChooser fc) { + indentIcon = new IndentIcon(); } /** @@ -586,28 +595,83 @@ * @return The list cell renderer. */ public Component getListCellRendererComponent(JList list, Object value, - int index, boolean isSelected, boolean cellHasFocus) + int index, + boolean isSelected, + boolean cellHasFocus) { - FileView fileView = getFileView(getFileChooser()); + super.getListCellRendererComponent(list, value, index, isSelected, + cellHasFocus); File file = (File) value; - setIcon(fileView.getIcon(file)); - setText(fileView.getName(file)); + setText(getFileChooser().getName(file)); - if (isSelected) + // Install indented icon. + Icon icon = getFileChooser().getIcon(file); + indentIcon.setIcon(icon); + int depth = directoryModel.getDepth(index); + indentIcon.setDepth(depth); + setIcon(indentIcon); + + return this; + } + } + + /** + * An icon that wraps another icon and adds indentation. + */ + class IndentIcon + implements Icon { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); + + /** + * The indentation level. + */ + private static final int INDENT = 10; + + /** + * The wrapped icon. + */ + private Icon icon; + + /** + * The current depth. + */ + private int depth; + + /** + * Sets the icon to be wrapped. + * + * @param i the icon + */ + void setIcon(Icon i) + { + icon = i; } - else + + /** + * Sets the indentation depth. + * + * @param d the depth to set + */ + void setDepth(int d) { - setBackground(list.getBackground()); - setForeground(list.getForeground()); + depth = d; } - setEnabled(list.isEnabled()); - setFont(list.getFont()); - return this; + public int getIconHeight() + { + return icon.getIconHeight(); } + + public int getIconWidth() + { + return icon.getIconWidth() + depth * INDENT; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + icon.paintIcon(c, g, x + depth * INDENT, y); + } + } /** @@ -956,9 +1020,12 @@ { String text = editField.getText(); if (text != null && text != "" && !text.equals(fc.getName(editFile))) - if (editFile.renameTo(fc.getFileSystemView().createFileObject( - fc.getCurrentDirectory(), text))) + { + File f = fc.getFileSystemView(). + createFileObject(fc.getCurrentDirectory(), text); + if ( editFile.renameTo(f) ) rescanCurrentDirectory(fc); + } list.remove(editField); } startEditing = false; @@ -982,17 +1049,8 @@ */ public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("notify-field-accept")) + if (editField != null) completeEditing(); - else if (editField != null) - { - list.remove(editField); - startEditing = false; - editFile = null; - lastSelected = null; - editField = null; - list.repaint(); - } } } } @@ -1101,7 +1159,7 @@ lastSelected = selVal; if (f.isFile()) setFileName(path.substring(path.lastIndexOf("/") + 1)); - else if (fc.getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) + else if (fc.getFileSelectionMode() != JFileChooser.FILES_ONLY) setFileName(path); } fileTable.repaint(); @@ -1171,16 +1229,8 @@ */ public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("notify-field-accept")) + if (editField != null) completeEditing(); - else if (editField != null) - { - table.remove(editField); - startEditing = false; - editFile = null; - editField = null; - table.repaint(); - } } } Modified: trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalIconFactory.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalIconFactory.java 2007-02-04 09:46:03 UTC (rev 3106) +++ trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalIconFactory.java 2007-02-04 10:20:16 UTC (rev 3107) @@ -1039,21 +1039,23 @@ g.drawLine(x + 6, y + 14, x, y + 8); g.drawLine(x, y + 7, x, y + 1); - // Fill the icon. - if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme - && enabled) +// The following is commented out until the masking for the gradient painting +// is working correctly +// // Fill the icon. +// if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme +// && enabled) +// { +// String gradient; +// if (focus) +// gradient = "Slider.focusGradient"; +// else +// gradient = "Slider.gradient"; +// MetalUtils.paintGradient(g, x + 1, y + 2, 12, 13, +// SwingConstants.VERTICAL, gradient, +// gradientMask); +// } +// else { - String gradient; - if (focus) - gradient = "Slider.focusGradient"; - else - gradient = "Slider.gradient"; - MetalUtils.paintGradient(g, x + 1, y + 2, 12, 13, - SwingConstants.VERTICAL, gradient, - gradientMask); - } - else - { if (focus) g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); else @@ -1700,21 +1702,23 @@ g.drawLine(x + 8, y + 14, x + 1, y + 14); g.drawLine(x, y + 13, x, y + 1); - // Fill the icon. - if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme - && enabled) +// The following is commented out until the masking for the gradient painting +// is working correctly +// // Fill the icon. +// if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme +// && enabled) +// { +// String gradient; +// if (focus) +// gradient = "Slider.focusGradient"; +// else +// gradient = "Slider.gradient"; +// MetalUtils.paintGradient(g, x + 2, y + 1, 13, 12, +// SwingConstants.HORIZONTAL, gradient, +// gradientMask); +// } +// else { - String gradient; - if (focus) - gradient = "Slider.focusGradient"; - else - gradient = "Slider.gradient"; - MetalUtils.paintGradient(g, x + 2, y + 1, 13, 12, - SwingConstants.HORIZONTAL, gradient, - gradientMask); - } - else - { if (focus) g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); else Modified: trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalRadioButtonUI.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalRadioButtonUI.java 2007-02-04 09:46:03 UTC (rev 3106) +++ trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalRadioButtonUI.java 2007-02-04 10:20:16 UTC (rev 3107) @@ -177,7 +177,7 @@ protected void paintFocus(Graphics g, Rectangle t, Dimension d) { g.setColor(focusColor); - g.drawRect(t.x - 1, t.y - 1, t.width + 2, t.height + 2); + g.drawRect(t.x - 1, t.y - 1, t.width + 1, t.height + 1); } } Modified: trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalScrollBarUI.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalScrollBarUI.java 2007-02-04 09:46:03 UTC (rev 3106) +++ trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalScrollBarUI.java 2007-02-04 10:20:16 UTC (rev 3107) @@ -1,5 +1,5 @@ /* MetalScrollBarUI.java - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -169,6 +169,7 @@ Boolean prop = (Boolean) scrollbar.getClientProperty(FREE_STANDING_PROP); isFreeStanding = prop == null ? true : prop.booleanValue(); scrollBarShadowColor = UIManager.getColor("ScrollBar.shadow"); + scrollBarWidth = UIManager.getInt("ScrollBar.width"); super.installDefaults(); } @@ -187,7 +188,10 @@ /** * Creates a new button to use as the control at the lower end of the - * {@link JScrollBar}. + * {@link JScrollBar}. This method assigns the new button (an instance of + * {@link MetalScrollButton} to the {@link #decreaseButton} field, and also + * returns the button. The button width is determined by the + * <code>ScrollBar.width</code> setting in the UI defaults. * * @param orientation the orientation of the button ({@link #NORTH}, * {@link #SOUTH}, {@link #EAST} or {@link #WEST}). @@ -196,7 +200,6 @@ */ protected JButton createDecreaseButton(int orientation) { - scrollBarWidth = UIManager.getInt("ScrollBar.width"); decreaseButton = new MetalScrollButton(orientation, scrollBarWidth, isFreeStanding); return decreaseButton; @@ -204,7 +207,10 @@ /** * Creates a new button to use as the control at the upper end of the - * {@link JScrollBar}. + * {@link JScrollBar}. This method assigns the new button (an instance of + * {@link MetalScrollButton} to the {@link #increaseButton} field, and also + * returns the button. The button width is determined by the + * <code>ScrollBar.width</code> setting in the UI defaults. * * @param orientation the orientation of the button ({@link #NORTH}, * {@link #SOUTH}, {@link #EAST} or {@link #WEST}). @@ -213,7 +219,6 @@ */ protected JButton createIncreaseButton(int orientation) { - scrollBarWidth = UIManager.getInt("ScrollBar.width"); increaseButton = new MetalScrollButton(orientation, scrollBarWidth, isFreeStanding); return increaseButton; Modified: trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalSliderUI.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalSliderUI.java 2007-02-04 09:46:03 UTC (rev 3106) +++ trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalSliderUI.java 2007-02-04 10:20:16 UTC (rev 3107) @@ -352,7 +352,10 @@ */ public int getTickLength() { - return tickLength + TICK_BUFFER; + int len = tickLength + TICK_BUFFER + 1; + if (slider.getOrientation() == JSlider.VERTICAL) + len += 2; + return len; } /** @@ -406,9 +409,9 @@ // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... if (slider.isEnabled()) - g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + g.setColor(slider.getForeground()); else - g.setColor(MetalLookAndFeel.getControlDisabled()); + g.setColor(MetalLookAndFeel.getControlShadow()); g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + tickLength / 2); } @@ -425,10 +428,10 @@ // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... if (slider.isEnabled()) - g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + g.setColor(slider.getForeground()); else - g.setColor(MetalLookAndFeel.getControlDisabled()); - g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + tickLength); + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + tickLength - 1); } /** @@ -444,10 +447,10 @@ // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... if (slider.isEnabled()) - g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + g.setColor(slider.getForeground()); else - g.setColor(MetalLookAndFeel.getControlDisabled()); - g.drawLine(TICK_BUFFER - 1, y, TICK_BUFFER - 1 + tickLength / 2, y); + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(TICK_BUFFER, y, TICK_BUFFER + tickLength / 2, y); } /** @@ -463,10 +466,10 @@ // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... if (slider.isEnabled()) - g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + g.setColor(slider.getForeground()); else - g.setColor(MetalLookAndFeel.getControlDisabled()); - g.drawLine(TICK_BUFFER - 1, y, TICK_BUFFER - 1 + tickLength, y); + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(TICK_BUFFER, y, TICK_BUFFER + tickLength, y); } } Modified: trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalUtils.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalUtils.java 2007-02-04 09:46:03 UTC (rev 3106) +++ trunk/core/src/classpath/javax/javax/swing/plaf/metal/MetalUtils.java 2007-02-04 10:20:16 UTC (rev 3107) @@ -41,6 +41,7 @@ import java.awt.Color; import java.awt.Component; +import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.TexturePaint; @@ -108,7 +109,7 @@ for (int mX = x + xOff; mX < (x + w); mX += 4) { - g.drawLine(mX, mY, mX, mY); + g.fillRect(mX, mY, 1, 1); } // increase x offset @@ -341,7 +342,7 @@ y0 = mask[xc - x0][0] + y; y1 = mask[xc - x0][1] + y; } - g.drawLine(xc, y0, xc, y1); + g.fillRect(xc, y0, 1, y1 - y0); } // Paint solid c2 area. g.setColor(c2); @@ -355,7 +356,7 @@ { y0 = mask[xc - x0][0] + y; y1 = mask[xc - x0][1] + y; - g.drawLine(xc, y0, xc, y1); + g.fillRect(xc, y0, 1, y1 - y0); } } @@ -379,7 +380,7 @@ y0 = mask[xc - x0][0] + y; y1 = mask[xc - x0][1] + y; } - g.drawLine(xc, y0, xc, y1); + g.fillRect(xc, y0, 1, y1 - y0); } // Paint third gradient area (c1->c3). @@ -423,7 +424,7 @@ * described above */ static void paintVerticalGradient(Graphics g, int x, int y, int w, int h, - double g1, double g2, Color c1, Color c2, + float g1, float g2, Color c1, Color c2, Color c3, int[][] mask) { // Calculate the coordinates. @@ -460,7 +461,7 @@ x0 = mask[yc - y0][0] + x; x1 = mask[yc - y0][1] + x; } - g.drawLine(x0, yc, x1, yc); + g.fillRect(x0, yc, x1 - x0, 1); } // Paint solid c2 area. g.setColor(c2); @@ -474,7 +475,7 @@ { x0 = mask[yc - y0][0] + x; x1 = mask[yc - y0][1] + x; - g.drawLine(x0, yc, x1, yc); + g.fillRect(x0, yc, x1 - x0, 1); } } @@ -498,7 +499,7 @@ x0 = mask[yc - y0][0] + x; x1 = mask[yc - y0][1] + x; } - g.drawLine(x0, yc, x1, yc); + g.fillRect(x0, yc, x1 - x0, 1); } // Paint third gradient area (c1->c3). @@ -521,7 +522,61 @@ x0 = mask[yc - y0][0] + x; x1 = mask[yc - y0][1] + x; } - g.drawLine(x0, yc, x1, yc); + g.fillRect(x0, yc, x1 - x0, 1); } } + + /** + * Paints a horizontal gradient using Graphics2D functionality. + * + * @param g the Graphics2D instance + * @param x the X coordinate of the upper left corner of the rectangle + * @param y the Y coordinate of the upper left corner of the rectangle + * @param w the width of the rectangle + * @param h the height of the rectangle + * @param g1 the relative width of the c1->c2 gradients + * @param g2 the relative width of the c2 solid area + * @param c1 the color 1 + * @param c2 the color 2 + * @param c3 the color 3 + * @param mask the mask that should be used when painting the gradient as + * described above + */ + private static void paintHorizontalGradient2D(Graphics2D g, int x, int y, + int w, int h, float g1, + float g2, Color c1, + Color c2, Color c3, + int[][] mask) + { + // FIXME: Handle the mask somehow, or do Graphics2D clipping instead. + GradientPaint p1 = new GradientPaint(x, y, c1, x + w * g1, y, c2); + g.setPaint(p1); + // This fills the first gradient and the solid area in one go. + g.fillRect(x, y, (int) (w * (g1 + g2)), h); + + GradientPaint p2 = new GradientPaint(x + (w * (g1 + g2)), y, c2, x + w, y, + c3); + g.setPaint(p2); + g.fillRect((int) (x + (w * (g1 + g2))), y, + (int) (w * (1. - (g1 + g2))), h); } + + private static void paintVerticalGradient2D(Graphics2D g, int x, int y, + int w, int h, float g1, + float g2, Color c1, + Color c2, Color c3, + int[][] mask) + { + // FIXME: Handle the mask somehow, or do Graphics2D clipping instead. + GradientPaint p1 = new GradientPaint(x, y, c1, x, y + h * g1, c2); + g.setPaint(p1); + // This fills the first gradient and the solid area in one go. + g.fillRect(x, y, w, (int) (h * (g1 + g2))); + + GradientPaint p2 = new GradientPaint(x, y + (h * (g1 + g2)), c2, x, y + h, + c3); + g.setPaint(p2); + g.fillRect(x, (int) (y + (h * (g1 + g2))), w, + (int) (h * (1. - (g1 + g2)))); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-04 09:46:30
|
Revision: 3106 http://jnode.svn.sourceforge.net/jnode/?rev=3106&view=rev Author: lsantha Date: 2007-02-04 01:46:03 -0800 (Sun, 04 Feb 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/javax/javax/swing/JComponent.java trunk/core/src/classpath/javax/javax/swing/JDialog.java trunk/core/src/classpath/javax/javax/swing/JFrame.java trunk/core/src/classpath/javax/javax/swing/JInternalFrame.java trunk/core/src/classpath/javax/javax/swing/JLabel.java trunk/core/src/classpath/javax/javax/swing/JLayeredPane.java trunk/core/src/classpath/javax/javax/swing/JMenuItem.java trunk/core/src/classpath/javax/javax/swing/JScrollBar.java trunk/core/src/classpath/javax/javax/swing/JSlider.java trunk/core/src/classpath/javax/javax/swing/JSplitPane.java trunk/core/src/classpath/javax/javax/swing/JTable.java trunk/core/src/classpath/javax/javax/swing/JTree.java trunk/core/src/classpath/javax/javax/swing/JViewport.java trunk/core/src/classpath/javax/javax/swing/RepaintManager.java trunk/core/src/classpath/javax/javax/swing/UIManager.java Modified: trunk/core/src/classpath/javax/javax/swing/JComponent.java =================================================================== --- trunk/core/src/classpath/javax/javax/swing/JComponent.java 2007-02-03 20:57:41 UTC (rev 3105) +++ trunk/core/src/classpath/javax/javax/swing/JComponent.java 2007-02-04 09:46:03 UTC (rev 3106) @@ -48,12 +48,10 @@ import java.awt.FocusTraversalPolicy; import java.awt.Font; import java.awt.Graphics; -import java.awt.Graphics2D; import java.awt.Image; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; -import java.awt.Shape; import java.awt.Window; import java.awt.dnd.DropTarget; import java.awt.event.ActionEvent; @@ -69,6 +67,7 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; +import java.beans.VetoableChangeSupport; import java.io.Serializable; import java.util.ArrayList; import java.util.EventListener; @@ -506,27 +505,6 @@ } /** - * An explicit value for the component's preferred size; if not set by a - * user, this is calculated on the fly by delegating to the {@link - * ComponentUI#getPreferredSize} method on the {@link #ui} property. - */ - Dimension preferredSize; - - /** - * An explicit value for the component's minimum size; if not set by a - * user, this is calculated on the fly by delegating to the {@link - * ComponentUI#getMinimumSize} method on the {@link #ui} property. - */ - Dimension minimumSize; - - /** - * An explicit value for the component's maximum size; if not set by a - * user, this is calculated on the fly by delegating to the {@link - * ComponentUI#getMaximumSize} method on the {@link #ui} property. - */ - Dimension maximumSize; - - /** * A value between 0.0 and 1.0 indicating the preferred horizontal * alignment of the component, relative to its siblings. The values * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link @@ -564,12 +542,19 @@ Border border; /** - * The text to show in the tooltip associated with this component. + * The popup menu for the component. * - * @see #setToolTipText - * @see #getToolTipText() + * @see #getComponentPopupMenu() + * @see #setComponentPopupMenu(JPopupMenu) */ - String toolTipText; + JPopupMenu componentPopupMenu; + + /** + * A flag that controls whether the {@link #getComponentPopupMenu()} method + * looks to the component's parent when the <code>componentPopupMenu</code> + * field is <code>null</code>. + */ + boolean inheritsPopupMenu; /** * <p>Whether to double buffer this component when painting. This flag @@ -668,9 +653,15 @@ * Indicates whether the current paint call is already double buffered or * not. */ - static boolean isPaintingDoubleBuffered = false; + static boolean paintingDoubleBuffered = false; /** + * Indicates whether we are calling paintDoubleBuffered() from + * paintImmadiately (RepaintManager) or from paint() (AWT refresh). + */ + static boolean isRepainting = false; + + /** * Listeners for events other than {@link PropertyChangeEvent} are * handled by this listener list. PropertyChangeEvents are handled in * {@link #changeSupport}. @@ -678,6 +669,11 @@ protected EventListenerList listenerList = new EventListenerList(); /** + * Handles VetoableChangeEvents. + */ + private VetoableChangeSupport vetoableChangeSupport; + + /** * Storage for "client properties", which are key/value pairs associated * with this component by a "client", such as a user application or a * layout manager. This is lazily constructed when the component gets its @@ -690,7 +686,7 @@ private ComponentInputMap inputMap_whenInFocusedWindow; private ActionMap actionMap; /** @since 1.3 */ - private boolean verifyInputWhenFocusTarget; + private boolean verifyInputWhenFocusTarget = true; private InputVerifier inputVerifier; private TransferHandler transferHandler; @@ -759,7 +755,14 @@ */ public static final int WHEN_IN_FOCUSED_WINDOW = 2; + /** + * Used to optimize painting. This is set in paintImmediately2() to specify + * the exact component path to be painted by paintChildren. + */ + Component paintChild; + + /** * Indicates if the opaque property has been set by a client program or by * the UI. * @@ -784,7 +787,7 @@ { super(); setDropTarget(new DropTarget()); - defaultLocale = Locale.getDefault(); + setLocale(getDefaultLocale()); debugGraphicsOptions = DebugGraphics.NONE_OPTION; setRequestFocusEnabled(true); } @@ -844,6 +847,11 @@ t.put(key, value); else t.remove(key); + + // When both old and new value are null, no event is fired. This is + // different from what firePropertyChange() normally does, so we add this + // check here. + if (old != null || value != null) firePropertyChange(key.toString(), old, value); } @@ -868,7 +876,8 @@ */ public void removeVetoableChangeListener(VetoableChangeListener listener) { - listenerList.remove(VetoableChangeListener.class, listener); + if (vetoableChangeSupport != null) + vetoableChangeSupport.removeVetoableChangeListener(listener); } /** @@ -884,23 +893,6 @@ } /** - * Register a <code>PropertyChangeListener</code> for a specific, named - * property. To listen to all property changes, regardless of name, use - * {@link #addPropertyChangeListener(PropertyChangeListener)} instead. - * - * @param propertyName The property name to listen to - * @param listener The listener to register - * - * @see #removePropertyChangeListener(String, PropertyChangeListener) - * @see #changeSupport - */ - public void addPropertyChangeListener(String propertyName, - PropertyChangeListener listener) - { - listenerList.add(PropertyChangeListener.class, listener); - } - - /** * Register a <code>VetoableChangeListener</code>. * * @param listener The listener to register @@ -910,7 +902,10 @@ */ public void addVetoableChangeListener(VetoableChangeListener listener) { - listenerList.add(VetoableChangeListener.class, listener); + // Lazily instantiate this, it's rarely needed. + if (vetoableChangeSupport == null) + vetoableChangeSupport = new VetoableChangeSupport(this); + vetoableChangeSupport.addVetoableChangeListener(listener); } /** @@ -932,10 +927,12 @@ * * @since 1.3 */ - public EventListener[] getListeners(Class listenerType) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { if (listenerType == PropertyChangeListener.class) - return getPropertyChangeListeners(); + return (T[]) getPropertyChangeListeners(); + else if (listenerType == VetoableChangeListener.class) + return (T[]) getVetoableChangeListeners(); else return listenerList.getListeners(listenerType); } @@ -954,60 +951,19 @@ /** * Return all registered <code>VetoableChangeListener</code> objects. * - * @return The set of <code>VetoableChangeListener</code> objects in {@link - * #listenerList} + * @return An array of the <code>VetoableChangeListener</code> objects + * registered with this component (possibly empty but never + * <code>null</code>). + * + * @since 1.4 */ public VetoableChangeListener[] getVetoableChangeListeners() { - return (VetoableChangeListener[]) getListeners(VetoableChangeListener.class); + return vetoableChangeSupport == null ? new VetoableChangeListener[0] + : vetoableChangeSupport.getVetoableChangeListeners(); } /** - * A variant of {@link #firePropertyChange(String,Object,Object)} - * for properties with <code>boolean</code> values. - * - * @specnote It seems that in JDK1.5 all property related methods have been - * moved to java.awt.Component, except this and 2 others. We call - * super here. I guess this will also be removed in one of the next - * releases. - */ - public void firePropertyChange(String propertyName, boolean oldValue, - boolean newValue) - { - super.firePropertyChange(propertyName, oldValue, newValue); - } - - /** - * A variant of {@link #firePropertyChange(String,Object,Object)} - * for properties with <code>char</code> values. - * - * @specnote It seems that in JDK1.5 all property related methods have been - * moved to java.awt.Component, except this and 2 others. We call - * super here. I guess this will also be removed in one of the next - * releases. - */ - public void firePropertyChange(String propertyName, char oldValue, - char newValue) - { - super.firePropertyChange(propertyName, oldValue, newValue); - } - - /** - * A variant of {@link #firePropertyChange(String,Object,Object)} - * for properties with <code>int</code> values. - * - * @specnote It seems that in JDK1.5 all property related methods have been - * moved to java.awt.Component, except this and 2 others. We call - * super here. I guess this will also be removed in one of the next - * releases. - */ - public void firePropertyChange(String propertyName, int oldValue, - int newValue) - { - super.firePropertyChange(propertyName, oldValue, newValue); - } - - /** * Call {@link VetoableChangeListener#vetoableChange} on all listeners * registered to listen to a given property. Any method which changes * the specified property of this component should call this method. @@ -1025,14 +981,45 @@ Object newValue) throws PropertyVetoException { - VetoableChangeListener[] listeners = getVetoableChangeListeners(); + if (vetoableChangeSupport != null) + vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue); + } - PropertyChangeEvent evt = - new PropertyChangeEvent(this, propertyName, oldValue, newValue); - for (int i = 0; i < listeners.length; i++) - listeners[i].vetoableChange(evt); + /** + * Fires a property change for a primitive integer property. + * + * @param property the name of the property + * @param oldValue the old value of the property + * @param newValue the new value of the property + * + * @specnote This method is implemented in + * {@link Component#firePropertyChange(String, int, int)}. It is + * only here because it is specified to be public, whereas the + * Component method is protected. + */ + public void firePropertyChange(String property, int oldValue, int newValue) + { + super.firePropertyChange(property, oldValue, newValue); } + + /** + * Fires a property change for a primitive boolean property. + * + * @param property the name of the property + * @param oldValue the old value of the property + * @param newValue the new value of the property + * + * @specnote This method is implemented in + * {@link Component#firePropertyChange(String, boolean, boolean)}. + * It is only here because it is specified to be public, whereas + * the Component method is protected. + */ + public void firePropertyChange(String property, boolean oldValue, + boolean newValue) + { + super.firePropertyChange(property, oldValue, newValue); + } /** * Get the value of the accessibleContext property for this component. @@ -1252,37 +1239,38 @@ } /** - * Get the component's maximum size. If the {@link #maximumSize} property - * has been explicitly set, it is returned. If the {@link #maximumSize} + * Get the component's maximum size. If the <code>maximumSize</code> property + * has been explicitly set, it is returned. If the <code>maximumSize</code> * property has not been set but the {@link #ui} property has been, the * result of {@link ComponentUI#getMaximumSize} is returned. If neither * property has been set, the result of {@link Container#getMaximumSize} * is returned. * - * @return The maximum size of the component + * @return the maximum size of the component * - * @see #maximumSize - * @see #setMaximumSize + * @see Component#setMaximumSize + * @see Component#getMaximumSize() + * @see Component#isMaximumSizeSet() + * @see ComponentUI#getMaximumSize(JComponent) */ public Dimension getMaximumSize() { - if (maximumSize != null) - return maximumSize; - - if (ui != null) + Dimension size = null; + if (isMaximumSizeSet()) + size = super.getMaximumSize(); + else { - Dimension s = ui.getMaximumSize(this); - if (s != null) - return s; + if (ui != null) + size = ui.getMaximumSize(this); + if (size == null) + size = super.getMaximumSize(); } - - Dimension p = super.getMaximumSize(); - return p; + return size; } /** - * Get the component's minimum size. If the {@link #minimumSize} property - * has been explicitly set, it is returned. If the {@link #minimumSize} + * Get the component's minimum size. If the <code>minimumSize</code> property + * has been explicitly set, it is returned. If the <code>minimumSize</code> * property has not been set but the {@link #ui} property has been, the * result of {@link ComponentUI#getMinimumSize} is returned. If neither * property has been set, the result of {@link Container#getMinimumSize} @@ -1290,95 +1278,55 @@ * * @return The minimum size of the component * - * @see #minimumSize - * @see #setMinimumSize + * @see Component#setMinimumSize + * @see Component#getMinimumSize() + * @see Component#isMinimumSizeSet() + * @see ComponentUI#getMinimumSize(JComponent) */ public Dimension getMinimumSize() { - if (minimumSize != null) - return minimumSize; - - if (ui != null) + Dimension size = null; + if (isMinimumSizeSet()) + size = super.getMinimumSize(); + else { - Dimension s = ui.getMinimumSize(this); - if (s != null) - return s; + if (ui != null) + size = ui.getMinimumSize(this); + if (size == null) + size = super.getMinimumSize(); } - - Dimension p = super.getMinimumSize(); - return p; + return size; } /** - * Get the component's preferred size. If the {@link #preferredSize} - * property has been explicitly set, it is returned. If the {@link - * #preferredSize} property has not been set but the {@link #ui} property - * has been, the result of {@link ComponentUI#getPreferredSize} is + * Get the component's preferred size. If the <code>preferredSize</code> + * property has been explicitly set, it is returned. If the + * <code>preferredSize</code> property has not been set but the {@link #ui} + * property has been, the result of {@link ComponentUI#getPreferredSize} is * returned. If neither property has been set, the result of {@link * Container#getPreferredSize} is returned. * * @return The preferred size of the component * - * @see #preferredSize - * @see #setPreferredSize + * @see Component#setPreferredSize + * @see Component#getPreferredSize() + * @see Component#isPreferredSizeSet() + * @see ComponentUI#getPreferredSize(JComponent) */ public Dimension getPreferredSize() { - Dimension prefSize = null; - if (preferredSize != null) - prefSize = new Dimension(preferredSize); - - else if (ui != null) - { - Dimension s = ui.getPreferredSize(this); - if (s != null) - prefSize = s; - } - - if (prefSize == null) - prefSize = super.getPreferredSize(); - - return prefSize; - } - - /** - * Checks if a maximum size was explicitely set on the component. - * - * @return <code>true</code> if a maximum size was set, - * <code>false</code> otherwise - * - * @since 1.3 - */ - public boolean isMaximumSizeSet() + Dimension size = null; + if (isPreferredSizeSet()) + size = super.getPreferredSize(); + else { - return maximumSize != null; + if (ui != null) + size = ui.getPreferredSize(this); + if (size == null) + size = super.getPreferredSize(); } - - /** - * Checks if a minimum size was explicitely set on the component. - * - * @return <code>true</code> if a minimum size was set, - * <code>false</code> otherwise - * - * @since 1.3 - */ - public boolean isMinimumSizeSet() - { - return minimumSize != null; + return size; } - - /** - * Checks if a preferred size was explicitely set on the component. - * - * @return <code>true</code> if a preferred size was set, - * <code>false</code> otherwise - * - * @since 1.3 - */ - public boolean isPreferredSizeSet() - { - return preferredSize != null; - } /** * Return the value of the <code>nextFocusableComponent</code> property. @@ -1402,11 +1350,32 @@ * Return the set of {@link KeyStroke} objects which are registered * to initiate actions on this component. * - * @return An array of the registered keystrokes + * @return An array of the registered keystrokes (possibly empty but never + * <code>null</code>). */ public KeyStroke[] getRegisteredKeyStrokes() { - return null; + KeyStroke[] ks0; + KeyStroke[] ks1; + KeyStroke[] ks2; + if (inputMap_whenFocused != null) + ks0 = inputMap_whenFocused.keys(); + else + ks0 = new KeyStroke[0]; + if (inputMap_whenAncestorOfFocused != null) + ks1 = inputMap_whenAncestorOfFocused.keys(); + else + ks1 = new KeyStroke[0]; + if (inputMap_whenInFocusedWindow != null) + ks2 = inputMap_whenInFocusedWindow.keys(); + else + ks2 = new KeyStroke[0]; + int count = ks0.length + ks1.length + ks2.length; + KeyStroke[] result = new KeyStroke[count]; + System.arraycopy(ks0, 0, result, 0, ks0.length); + System.arraycopy(ks1, 0, result, ks0.length, ks1.length); + System.arraycopy(ks2, 0, result, ks0.length + ks1.length, ks2.length); + return result; } /** @@ -1452,14 +1421,12 @@ { JToolTip toolTip = new JToolTip(); toolTip.setComponent(this); - toolTip.setTipText(toolTipText); - return toolTip; } /** - * Return the location at which the {@link #toolTipText} property should be - * displayed, when triggered by a particular mouse event. + * Return the location at which the <code>toolTipText</code> property should + * be displayed, when triggered by a particular mouse event. * * @param event The event the tooltip is being presented in response to * @@ -1472,53 +1439,56 @@ } /** - * Set the value of the {@link #toolTipText} property. + * Set the tooltip text for this component. If a non-<code>null</code> + * value is set, this component is registered in the + * <code>ToolTipManager</code> in order to turn on tooltips for this + * component. If a <code>null</code> value is set, tooltips are turne off + * for this component. * - * @param text The new property value + * @param text the tooltip text for this component * * @see #getToolTipText() + * @see #getToolTipText(MouseEvent) */ public void setToolTipText(String text) { + String old = getToolTipText(); + putClientProperty(TOOL_TIP_TEXT_KEY, text); + ToolTipManager ttm = ToolTipManager.sharedInstance(); if (text == null) - { - ToolTipManager.sharedInstance().unregisterComponent(this); - toolTipText = null; - return; - } - - // XXX: The tip text doesn't get updated unless you set it to null - // and then to something not-null. This is consistent with the behaviour - // of Sun's ToolTipManager. - - String oldText = toolTipText; - toolTipText = text; - - if (oldText == null) - ToolTipManager.sharedInstance().registerComponent(this); + ttm.unregisterComponent(this); + else if (old == null) + ttm.registerComponent(this); } /** - * Get the value of the {@link #toolTipText} property. + * Returns the current tooltip text for this component, or <code>null</code> + * if none has been set. * - * @return The current property value + * @return the current tooltip text for this component, or <code>null</code> + * if none has been set * * @see #setToolTipText + * @see #getToolTipText(MouseEvent) */ public String getToolTipText() { - return toolTipText; + return (String) getClientProperty(TOOL_TIP_TEXT_KEY); } /** - * Get the value of the {@link #toolTipText} property, in response to a - * particular mouse event. + * Returns the tooltip text for this component for a particular mouse + * event. This can be used to support context sensitive tooltips that can + * change with the mouse location. By default this returns the static + * tooltip text returned by {@link #getToolTipText()}. * - * @param event The mouse event which triggered the tooltip + * @param event the mouse event which triggered the tooltip * - * @return The current property value + * @return the tooltip text for this component for a particular mouse + * event * * @see #setToolTipText + * @see #getToolTipText() */ public String getToolTipText(MouseEvent event) { @@ -1526,6 +1496,88 @@ } /** + * Returns the flag that controls whether or not the component inherits its + * parent's popup menu when no popup menu is specified for this component. + * + * @return A boolean. + * + * @since 1.5 + * + * @see #setInheritsPopupMenu(boolean) + */ + public boolean getInheritsPopupMenu() + { + return inheritsPopupMenu; + } + + /** + * Sets the flag that controls whether or not the component inherits its + * parent's popup menu when no popup menu is specified for this component. + * This is a bound property with the property name 'inheritsPopupMenu'. + * + * @param inherit the new flag value. + * + * @since 1.5 + * + * @see #getInheritsPopupMenu() + */ + public void setInheritsPopupMenu(boolean inherit) + { + if (inheritsPopupMenu != inherit) + { + inheritsPopupMenu = inherit; + this.firePropertyChange("inheritsPopupMenu", ! inherit, inherit); + } + } + + /** + * Returns the popup menu for this component. If the popup menu is + * <code>null</code> AND the {@link #getInheritsPopupMenu()} method returns + * <code>true</code>, this method will return the parent's popup menu (if it + * has one). + * + * @return The popup menu (possibly <code>null</code>. + * + * @since 1.5 + * + * @see #setComponentPopupMenu(JPopupMenu) + * @see #getInheritsPopupMenu() + */ + public JPopupMenu getComponentPopupMenu() + { + if (componentPopupMenu == null && getInheritsPopupMenu()) + { + Container parent = getParent(); + if (parent instanceof JComponent) + return ((JComponent) parent).getComponentPopupMenu(); + else + return null; + } + else + return componentPopupMenu; + } + + /** + * Sets the popup menu for this component (this is a bound property with + * the property name 'componentPopupMenu'). + * + * @param popup the popup menu (<code>null</code> permitted). + * + * @since 1.5 + * + * @see #getComponentPopupMenu() + */ + public void setComponentPopupMenu(JPopupMenu popup) + { + if (componentPopupMenu != popup) + { + JPopupMenu old = componentPopupMenu; + componentPopupMenu = popup; + firePropertyChange("componentPopupMenu", old, popup); + } + } + + /** * Return the top level ancestral container (usually a {@link * java.awt.Window} or {@link java.applet.Applet}) which this component is * contained within, or <code>null</code> if no ancestors exist. @@ -1725,11 +1777,11 @@ // buffer. When this method completes, the call stack unwinds back to // paintDoubleBuffered, where the buffer contents is finally drawn to the // screen. - if (!isPaintingDoubleBuffered && isDoubleBuffered() + if (!paintingDoubleBuffered && isDoubleBuffered() && rm.isDoubleBufferingEnabled()) { Rectangle clip = g.getClipBounds(); - paintDoubleBuffered(clip); + paintDoubleBuffered(clip.x, clip.y, clip.width, clip.height); } else { @@ -1744,8 +1796,22 @@ dragBuffer = null; } - if (g.getClip() == null) - g.setClip(0, 0, getWidth(), getHeight()); + Rectangle clip = g.getClipBounds(); + int clipX, clipY, clipW, clipH; + if (clip == null) + { + clipX = 0; + clipY = 0; + clipW = getWidth(); + clipH = getHeight(); + } + else + { + clipX = clip.x; + clipY = clip.y; + clipW = clip.width; + clipH = clip.height; + } if (dragBuffer != null && dragBufferInitialized) { g.drawImage(dragBuffer, 0, 0, this); @@ -1753,14 +1819,51 @@ else { Graphics g2 = getComponentGraphics(g); + if (! isOccupiedByChild(clipX, clipY, clipW, clipH)) + { paintComponent(g2); paintBorder(g2); + } paintChildren(g2); } } } /** + * Determines if a region of this component is completely occupied by + * an opaque child component, in which case we don't need to bother + * painting this component at all. + * + * @param x the area, x coordinate + * @param y the area, y coordinate + * @param w the area, width + * @param h the area, height + * + * @return <code>true</code> if the specified area is completely covered + * by a child component, <code>false</code> otherwise + */ + private boolean isOccupiedByChild(int x, int y, int w, int h) + { + boolean occupied = false; + int count = getComponentCount(); + for (int i = 0; i < count; i++) + { + Component child = getComponent(i); + int cx = child.getX(); + int cy = child.getY(); + int cw = child.getWidth(); + int ch = child.getHeight(); + if (child.isVisible() && x >= cx && x + w <= cx + cw && y >= cy + && y + h <= cy + ch) + { + occupied = child.isOpaque(); + break; + } + } + return occupied; + } + + /** * Initializes the drag buffer by creating a new image and painting this * component into it. */ @@ -1816,235 +1919,122 @@ { if (getComponentCount() > 0) { - if (isOptimizedDrawingEnabled()) - paintChildrenOptimized(g); - else - paintChildrenWithOverlap(g); - } - } - - /** - * Paints the children of this JComponent in the case when the component - * is not marked as optimizedDrawingEnabled, that means the container cannot - * guarantee that it's children are tiled. For this case we must - * perform a more complex optimization to determine the minimal rectangle - * to be painted for each child component. - * - * @param g the graphics context to use - */ - private void paintChildrenWithOverlap(Graphics g) - { - Shape originalClip = g.getClip(); - Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache); - g.clipRect(inner.x, inner.y, inner.width, inner.height); - Component[] children = getComponents(); - - // Find the rectangles that need to be painted for each child component. - // We push on this list arrays that have the Rectangles to be painted as - // the first elements and the component to be painted as the last one. - // Later we go through that list in reverse order and paint the rectangles. - ArrayList paintRegions = new ArrayList(children.length); - ArrayList paintRectangles = new ArrayList(); - ArrayList newPaintRects = new ArrayList(); - paintRectangles.add(g.getClipBounds()); - ArrayList componentRectangles = new ArrayList(); - - // Go through children from top to bottom and find out their paint - // rectangles. - for (int index = 0; paintRectangles.size() > 0 && - index < children.length; index++) - { - Component comp = children[index]; - if (! comp.isVisible()) - continue; - - Rectangle compBounds = comp.getBounds(); - boolean isOpaque = comp instanceof JComponent - && ((JComponent) comp).isOpaque(); - - // Add all the current paint rectangles that intersect with the - // component to the component's paint rectangle array. - for (int i = paintRectangles.size() - 1; i >= 0; i--) - { - Rectangle r = (Rectangle) paintRectangles.get(i); - if (r.intersects(compBounds)) + // Need to lock the tree to avoid problems with AWT and concurrency. + synchronized (getTreeLock()) + { + // Fast forward to the child to paint, if set by + // paintImmediately2() + int i = getComponentCount() - 1; + if (paintChild != null && paintChild.isOpaque()) { - Rectangle compRect = r.intersection(compBounds); - componentRectangles.add(compRect); - // If the component is opaque, split up each paint rect and - // add paintRect - compBounds to the newPaintRects array. - if (isOpaque) + for (; i >= 0 && getComponent(i) != paintChild; i--) + ; + } + for (; i >= 0; i--) + { + Component child = getComponent(i); + if (child != null && child.isLightweight() + && child.isVisible()) { - int x, y, w, h; - Rectangle rect = new Rectangle(); - - // The north retangle. - x = Math.max(compBounds.x, r.x); - y = r.y; - w = Math.min(compBounds.width, r.width + r.x - x); - h = compBounds.y - r.y; - rect.setBounds(x, y, w, h); - if (! rect.isEmpty()) + int cx = child.getX(); + int cy = child.getY(); + int cw = child.getWidth(); + int ch = child.getHeight(); + if (g.hitClip(cx, cy, cw, ch)) { - newPaintRects.add(rect); - rect = new Rectangle(); - } - - // The south rectangle. - x = Math.max(compBounds.x, r.x); - y = compBounds.y + compBounds.height; - w = Math.min(compBounds.width, r.width + r.x - x); - h = r.height - (compBounds.y - r.y) - compBounds.height; - rect.setBounds(x, y, w, h); - if (! rect.isEmpty()) + if ((! isOptimizedDrawingEnabled()) && i > 0) + { + // Check if the child is completely obscured. + Rectangle clip = g.getClipBounds(); // A copy. + SwingUtilities.computeIntersection(cx, cy, cw, ch, + clip); + if (isCompletelyObscured(i, clip.x, clip.y, + clip.width, clip.height)) + continue; // Continues the for-loop. + } + Graphics cg = g.create(cx, cy, cw, ch); + cg.setColor(child.getForeground()); + cg.setFont(child.getFont()); + try { - newPaintRects.add(rect); - rect = new Rectangle(); + child.paint(cg); } - - // The west rectangle. - x = r.x; - y = r.y; - w = compBounds.x - r.x; - h = r.height; - rect.setBounds(x, y, w, h); - if (! rect.isEmpty()) + finally { - newPaintRects.add(rect); - rect = new Rectangle(); + cg.dispose(); } - - // The east rectangle. - x = compBounds.x + compBounds.width; - y = r.y; - w = r.width - (compBounds.x - r.x) - compBounds.width; - h = r.height; - rect.setBounds(x, y, w, h); - if (! rect.isEmpty()) - { - newPaintRects.add(rect); - } } - else - { - // Not opaque, need to reuse the current paint rectangles - // for the next component. - newPaintRects.add(r); } - } - else - { - newPaintRects.add(r); - } } - - // Replace the paintRectangles with the new split up - // paintRectangles. - paintRectangles.clear(); - paintRectangles.addAll(newPaintRects); - newPaintRects.clear(); - - // Store paint rectangles if there are any for the current component. - int compRectsSize = componentRectangles.size(); - if (compRectsSize > 0) - { - componentRectangles.add(comp); - paintRegions.add(componentRectangles); - componentRectangles = new ArrayList(); } } - // paintingTile becomes true just before we start painting the component's - // children. - paintingTile = true; - - // We must go through the painting regions backwards, because the - // topmost components have been added first, followed by the components - // below. - int prEndIndex = paintRegions.size() - 1; - for (int i = prEndIndex; i >= 0; i--) + /** + * Determines if a region of a child component is completely obscured by one + * of its siblings. + * + * @param index the index of the child component + * @param x the region to check, x coordinate + * @param y the region to check, y coordinate + * @param w the region to check, width + * @param h the region to check, height + * + * @return <code>true</code> if the region is completely obscured by a + * sibling, <code>false</code> otherwise + */ + private boolean isCompletelyObscured(int index, int x, int y, int w, int h) { - // paintingTile must be set to false before we begin to start painting - // the last tile. - if (i == 0) - paintingTile = false; - - ArrayList paintingRects = (ArrayList) paintRegions.get(i); - // The last element is always the component. - Component c = (Component) paintingRects.get(paintingRects.size() - 1); - int endIndex = paintingRects.size() - 2; - for (int j = 0; j <= endIndex; j++) + boolean obscured = false; + for (int i = index - 1; i >= 0 && obscured == false; i--) { - Rectangle cBounds = c.getBounds(); - Rectangle bounds = (Rectangle) paintingRects.get(j); - Rectangle oldClip = g.getClipBounds(); - if (oldClip == null) - oldClip = bounds; - - boolean translated = false; - try + Component sib = getComponent(i); + if (sib.isVisible()) { - g.setClip(bounds); - g.translate(cBounds.x, cBounds.y); - translated = true; - c.paint(g); - } - finally + Rectangle sibRect = sib.getBounds(rectCache); + if (sib.isOpaque() && x >= sibRect.x + && (x + w) <= (sibRect.x + sibRect.width) + && y >= sibRect.y + && (y + h) <= (sibRect.y + sibRect.height)) { - if (translated) - g.translate(-cBounds.x, -cBounds.y); - g.setClip(oldClip); + obscured = true; } } } - g.setClip(originalClip); + return obscured; } /** - * Paints the children of this container when it is marked as - * optimizedDrawingEnabled. In this case the container can guarantee that - * it's children are tiled, which allows for a much more efficient - * algorithm to determine the minimum rectangles to be painted for - * each child. + * Checks if a component/rectangle is partially obscured by one of its + * siblings. + * Note that this doesn't check for completely obscured, this is + * done by isCompletelyObscured() and should probably also be checked. * - * @param g the graphics context to use + * @param i the component index from which to start searching + * @param x the x coordinate of the rectangle to check + * @param y the y coordinate of the rectangle to check + * @param w the width of the rectangle to check + * @param h the height of the rectangle to check + * + * @return <code>true</code> if the rectangle is partially obscured */ - private void paintChildrenOptimized(Graphics g) + private boolean isPartiallyObscured(int i, int x, int y, int w, int h) { - Shape originalClip = g.getClip(); - Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache); - g.clipRect(inner.x, inner.y, inner.width, inner.height); - Component[] children = getComponents(); - - // paintingTile becomes true just before we start painting the component's - // children. - paintingTile = true; - for (int i = children.length - 1; i >= 0; i--) //children.length; i++) + boolean obscured = false; + for (int j = i - 1; j >= 0 && ! obscured; j--) { - // paintingTile must be set to false before we begin to start painting - // the last tile. - if (i == children.length - 1) - paintingTile = false; - - if (!children[i].isVisible()) - continue; - - Rectangle bounds = children[i].getBounds(rectCache); - Rectangle oldClip = g.getClipBounds(); - if (oldClip == null) - oldClip = bounds; - - if (!g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height)) - continue; - - boolean translated = false; - Graphics g2 = g.create(bounds.x, bounds.y, bounds.width, - bounds.height); - children[i].paint(g2); - g2.dispose(); + Component sibl = getComponent(j); + if (sibl.isVisible()) + { + Rectangle rect = sibl.getBounds(rectCache); + if (!(x + w <= rect.x) + || (y + h <= rect.y) + || (x >= rect.x + rect.width) + || (y >= rect.y + rect.height)) + obscured = true; + } } - g.setClip(originalClip); + return obscured; } /** @@ -2064,14 +2054,17 @@ { if (ui != null) { - Graphics g2 = g; - if (!(g instanceof Graphics2D)) - g2 = g.create(); + Graphics g2 = g.create(); + try + { ui.update(g2, this); - if (!(g instanceof Graphics2D)) + } + finally + { g2.dispose(); } } + } /** * A variant of {@link #paintImmediately(Rectangle)} which takes @@ -2084,7 +2077,26 @@ */ public void paintImmediately(int x, int y, int w, int h) { - paintImmediately(new Rectangle(x, y, w, h)); + // Find opaque parent and call paintImmediately2() on it. + if (isShowing()) + { + Component c = this; + Component p; + while (c != null && ! c.isOpaque()) + { + p = c.getParent(); + if (p != null) + { + x += c.getX(); + y += c.getY(); + c = p; + } + } + if (c instanceof JComponent) + ((JComponent) c).paintImmediately2(x, y, w, h); + else + c.repaint(x, y, w, h); + } } /** @@ -2107,102 +2119,267 @@ */ public void paintImmediately(Rectangle r) { - // Try to find a root pane for this component. - //Component root = findPaintRoot(r); - Component root = findPaintRoot(r); - // If no paint root is found, then this component is completely overlapped - // by another component and we don't need repainting. - if (root == null) - return; - if (root == null || !root.isShowing()) - return; - - Rectangle rootClip = SwingUtilities.convertRectangle(this, r, root); - if (root instanceof JComponent) - ((JComponent) root).paintImmediately2(rootClip); - else - root.repaint(rootClip.x, rootClip.y, rootClip.width, rootClip.height); + paintImmediately(r.x, r.y, r.width, r.height); } /** * Performs the actual work of paintImmediatly on the repaint root. * - * @param r the area to be repainted + * @param x the area to be repainted, X coordinate + * @param y the area to be repainted, Y coordinate */ - void paintImmediately2(Rectangle r) + void paintImmediately2(int x, int y, int w, int h) { + // Optimization for components that are always painted on top. + boolean onTop = onTop() && isOpaque(); + + // Fetch the RepaintManager. RepaintManager rm = RepaintManager.currentManager(this); - if (rm.isDoubleBufferingEnabled() && isDoubleBuffered()) - paintDoubleBuffered(r); + + // The painting clip; + int paintX = x; + int paintY = y; + int paintW = w; + int paintH = h; + + // If we should paint buffered or not. + boolean haveBuffer = false; + + // The component that is finally triggered for painting. + JComponent paintRoot = this; + + // Stores the component and all its parents. This will be used to limit + // the actually painted components in paintChildren by setting + // the field paintChild. + int pIndex = -1; + int pCount = 0; + ArrayList components = new ArrayList(); + + // Offset to subtract from the paintRoot rectangle when painting. + int offsX = 0; + int offsY = 0; + + // The current component and its child. + Component child; + Container c; + + // Find appropriate paint root. + for (c = this, child = null; + c != null && ! (c instanceof Window) && ! (c instanceof Applet); + child = c, c = c.getParent()) + { + JComponent jc = c instanceof JComponent ? (JComponent) c : null; + components.add(c); + if (! onTop && jc != null && ! jc.isOptimizedDrawingEnabled()) + { + // Indicates whether we reset the paint root to be the current + // component. + boolean updatePaintRoot = false; + + // Check obscured state of the child. + // Generally, we have 3 cases here: + // 1. Not obscured. No need to paint from the parent. + // 2. Partially obscured. Paint from the parent. + // 3. Completely obscured. No need to paint anything. + if (c != this) + { + if (jc.isPaintRoot()) + updatePaintRoot = true; else - paintSimple(r); + { + int count = c.getComponentCount(); + int i = 0; + for (; i < count && c.getComponent(i) != child; i++) + ; + + if (jc.isCompletelyObscured(i, paintX, paintY, paintW, + paintH)) + return; // No need to paint anything. + else if (jc.isPartiallyObscured(i, paintX, paintY, paintW, + paintH)) + updatePaintRoot = true; + + } + } + if (updatePaintRoot) + { + // Paint from parent. + paintRoot = jc; + pIndex = pCount; + offsX = 0; + offsY = 0; + haveBuffer = false; + } + } + pCount++; + // Check if component is double buffered. + if (rm.isDoubleBufferingEnabled() && jc != null + && jc.isDoubleBuffered()) + { + haveBuffer = true; + } + + // Clip the paint region with the parent. + if (! onTop) + { + paintX = Math.max(0, paintX); + paintY = Math.max(0, paintY); + paintW = Math.min(c.getWidth(), paintW + paintX) - paintX; + paintH = Math.min(c.getHeight(), paintH + paintY) - paintY; + int dx = c.getX(); + int dy = c.getY(); + paintX += dx; + paintY += dy; + offsX += dx; + offsY += dy; + } + } + if (c != null && c.getPeer() != null && paintW > 0 && paintH > 0) + { + isRepainting = true; + paintX -= offsX; + paintY -= offsY; + + // Set the painting path so that paintChildren paints only what we + // want. + if (paintRoot != this) + { + for (int i = pIndex; i > 0; i--) + { + Component paintParent = (Component) components.get(i); + if (paintParent instanceof JComponent) + ((JComponent) paintParent).paintChild = + (Component) components.get(i - 1); + } + } + + // Actually trigger painting. + if (haveBuffer) + paintRoot.paintDoubleBuffered(paintX, paintY, paintW, paintH); + else + { + Graphics g = paintRoot.getGraphics(); + try + { + g.setClip(paintX, paintY, paintW, paintH); + paintRoot.paint(g); + } + finally + { + g.dispose(); + } + } + + // Reset the painting path. + if (paintRoot != this) + { + for (int i = pIndex; i > 0; i--) + { + Component paintParent = (Component) components.get(i); + if (paintParent instanceof JComponent) + ((JComponent) paintParent).paintChild = null; + } + } + + isRepainting = false; + } } /** - * Gets the root of the component given. If a parent of the - * component is an instance of Applet, then the applet is - * returned. The applet is considered the root for painting - * and adding/removing components. Otherwise, the root Window - * is returned if it exists. + * Returns <code>true</code> if the component is guaranteed to be painted + * on top of others. This returns false by default and is overridden by + * components like JMenuItem, JPopupMenu and JToolTip to return true for + * added efficiency. * - * @param comp - The component to get the root for. - * @return the parent root. An applet if it is a parent, - * or the root window. If neither exist, null is returned. + * @return <code>true</code> if the component is guaranteed to be painted + * on top of others */ - private Component getRoot(Component comp) + boolean onTop() { - Applet app = null; - - while (comp != null) - { - if (app == null && comp instanceof Window) - return comp; - else if (comp instanceof Applet) - app = (Applet) comp; - comp = comp.getParent(); + return false; } - return app; + /** + * This returns true when a component needs to force itself as a paint + * origin. This is used for example in JViewport to make sure that it + * gets to update its backbuffer. + * + * @return true when a component needs to force itself as a paint + * origin + */ + boolean isPaintRoot() + { + return false; } /** * Performs double buffered repainting. */ - private void paintDoubleBuffered(Rectangle r) + private void paintDoubleBuffered(int x, int y, int w, int h) { RepaintManager rm = RepaintManager.currentManager(this); // Paint on the offscreen buffer. - Component root = getRoot(this); + Component root = SwingUtilities.getRoot(this); Image buffer = rm.getVolatileOffscreenBuffer(this, root.getWidth(), root.getHeight()); + // The volatile offscreen buffer may be null when that's not supported // by the AWT backend. Fall back to normal backbuffer in this case. if (buffer == null) buffer = rm.getOffscreenBuffer(this, root.getWidth(), root.getHeight()); //Rectangle targetClip = SwingUtilities.convertRectangle(this, r, root); - Point translation = SwingUtilities.convertPoint(this, 0, 0, root); Graphics g2 = buffer.getGraphics(); - g2.translate(translation.x, translation.y); - g2.setClip(r.x, r.y, r.width, r.height); + clipAndTranslateGraphics(root, this, g2); + g2.clipRect(x, y, w, h); g2 = getComponentGraphics(g2); - isPaintingDoubleBuffered = true; + paintingDoubleBuffered = true; try { + if (isRepainting) // Called from paintImmediately, go through paint(). paint(g2); + else // Called from paint() (AWT refresh), don't call it again. + { + paintComponent(g2); + paintBorder(g2); + paintChildren(g2); + } } finally { - isPaintingDoubleBuffered = false; + paintingDoubleBuffered = false; g2.dispose(); } // Paint the buffer contents on screen. - rm.commitBuffer(root, new Rectangle(translation.x + r.x, - translation.y + r.y, r.width, - r.height)); + rm.commitBuffer(this, x, y, w, h); + } + + /** + * Clips and translates the Graphics instance for painting on the double + * buffer. This has to be done, so that it reflects the component clip of the + * target component. + * + * @param root the root component (top-level container usually) + * @param target the component to be painted + * @param g the Graphics instance + */ + private void clipAndTranslateGraphics(Component root, Component target, + Graphics g) + { + Component parent = target; + int deltaX = 0; + int deltaY = 0; + while (parent != root) + { + deltaX += parent.getX(); + deltaY += parent.getY(); + parent = parent.getParent(); } + g.translate(deltaX, deltaY); + g.clipRect(0, 0, target.getWidth(), target.getHeight()); + } /** * Performs normal painting without double buffering. @@ -2251,6 +2428,12 @@ * A variant of {@link * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which * provides <code>null</code> for the command name. + * + * @param act the action listener to notify when the keystroke occurs. + * @param stroke the key stroke. + * @param cond the condition (one of {@link #WHEN_FOCUSED}, + * {@link #WHEN_IN_FOCUSED_WINDOW} and + * {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}). */ public void registerKeyboardAction(ActionListener act, KeyStroke stroke, @@ -2327,9 +2510,22 @@ KeyStroke stroke, int cond) { - getInputMap(cond).put(stroke, new ActionListenerProxy(act, cmd)); + ActionListenerProxy proxy = new ActionListenerProxy(act, cmd); + getInputMap(cond).put(stroke, proxy); + getActionMap().put(proxy, proxy); } + /** + * Sets the input map for the given condition. + * + * @param condition the condition (one of {@link #WHEN_FOCUSED}, + * {@link #WHEN_IN_FOCUSED_WINDOW} and + * {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}). + * @param map the map. + * + * @throws IllegalArgumentException if <code>condition</code> is not one of + * the specified values. + */ public final void setInputMap(int condition, InputMap map) { enableEvents(AWTEvent.KEY_EVENT_MASK); @@ -2465,13 +2661,17 @@ */ public ActionListener getActionForKeyStroke(KeyStroke ks) { - Object cmd = getInputMap().get(ks); - if (cmd != null) + Object key = getInputMap(JComponent.WHEN_FOCUSED).get(ks); + if (key == null) + key = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).get(ks); + if (key == null) + key = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).get(ks); + if (key != null) { - if (cmd instanceof ActionListenerProxy) - return (ActionListenerProxy) cmd; - else if (cmd instanceof String) - return getActionMap().get(cmd); + if (key instanceof ActionListenerProxy) + return ((ActionListenerProxy) key).target; + else + return getActionMap().get(key); } return null; } @@ -2570,20 +2770,37 @@ if (isEnabled()) { Action act = null; + Object cmd = null; InputMap map = getInputMap(condition); if (map != null) { - Object cmd = map.get(ks); + cmd = map.get(ks); if (cmd != null) { if (cmd instanceof ActionListenerProxy) act = (Action) cmd; else - act = (Action) getActionMap().get(cmd); + act = getActionMap().get(cmd); } } if (act != null && act.isEnabled()) - return SwingUtilities.notifyAction(act, ks, e, this, e.getModifiers()); + { + // Need to synchronize here so we don't get in trouble with + // our __command__ hack. + synchronized (act) + { + // We add the command as value to the action, so that + // the action can later determine the command with which it + // was called. This is undocumented, but shouldn't affect + // compatibility. It allows us to use only one Action instance + // to do the work for all components of one type, instead of + // having loads of small Actions. This effectivly saves startup + // time of Swing. + act.putValue("__command__", cmd); + return SwingUtilities.notifyAction(act, ks, e, this, + e.getModifiers()); + } + } } return false; } @@ -2685,6 +2902,11 @@ */ public void revalidate() { + // As long as we don't have a parent we don't need to do any layout, since + // this is done anyway as soon as we get connected to a parent. + if (getParent() == null) + return; + if (! EventQueue.isDispatchThread()) SwingUtilities.invokeLater(new Runnable() { @@ -2708,9 +2930,25 @@ */ public void scrollRectToVisible(Rectangle r) { - Component p = getParent(); - if (p instanceof JComponent) - ((JComponent) p).scrollRectToVisible(r); + // Search nearest JComponent. + int xOffs = getX(); + int yOffs = getY(); + Component p; + for (p = getParent(); p != null && ! (p instanceof JComponent); + p = p.getParent()) + { + xOffs += p.getX(); + yOffs += p.getY(); + } + if (p != null) + { + r.x += xOffs; + r.y += yOffs; + JComponent jParent = (JComponent) p; + jParent.scrollRectToVisible(r); + r.x -= xOffs; + r.y -= yOffs; + } } /** @@ -2829,57 +3067,6 @@ } /** - * Set the value of the {@link #maximumSize} property. The passed value is - * copied, the later direct changes on the argument have no effect on the - * property value. - * - * @param max The new value of the property - */ - public void setMaximumSize(Dimension max) - { - Dimension oldMaximumSize = maximumSize; - if (max != null) - maximumSize = new Dimension(max); - else - maximumSize = null; - firePropertyChange("maximumSize", oldMaximumSize, maximumSize); - } - - /** - * Set the value of the {@link #minimumSize} property. The passed value is - * copied, the later direct changes on the argument have no effect on the - * property value. - * - * @param min The new value of the property - */ - public void setMinimumSize(Dimension min) - { - Dimension oldMinimumSize = minimumSize; - if (min != null) - minimumSize = new Dimension(min); - else - minimumSize = null; - firePropertyChange("minimumSize", oldMinimumSize, minimumSize); - } - - /** - * Set the value of the {@link #preferredSize} property. The passed value is - * copied, the later direct changes on the argument have no effect on the - * property value. - * - * @param pref The new value of the property - */ - public void setPreferredSize(Dimension pref) - { - Dimension oldPreferredSize = preferredSize; - if (pref != null) - preferredSize = new Dimension(pref); - else - preferredSize = null; - firePropertyChange("preferredSize", oldPreferredSize, preferredSize); - } - - /** * Set the specified component to be the next component in the * focus cycle, overriding the {@link FocusTraversalPolicy} for * this component. @@ -3068,11 +3255,29 @@ // Nothing to do here. } + /** + * Returns the locale used as the default for all new components. The + * default value is {@link Locale#getDefault()} (that is, the platform + * default locale). + * + * @return The locale (never <code>null</code>). + * + * @see #setDefaultLocale(Locale) + */ public static Locale getDefaultLocale() { + if (defaultLocale == null) + defaultLocale = Locale.getDefault(); return defaultLocale; } + /** + * Sets the locale to be used as the default for all new components. If this + * is set to <code>null</code>, the {@link #getDefaultLocale()} method will + * return the platform default locale. + * + * @param l the locale (<code>null</code> permitted). + */ public static void setDefaultLocale(Locale l) { defaultLocale = l; @@ -3510,141 +3715,18 @@ } } // Dispatch event to all children. - Component[] children = getComponents(); - for (int i = 0; i < children.leng... [truncated message content] |
From: <ls...@us...> - 2007-02-03 20:57:42
|
Revision: 3105 http://jnode.svn.sourceforge.net/jnode/?rev=3105&view=rev Author: lsantha Date: 2007-02-03 12:57:41 -0800 (Sat, 03 Feb 2007) Log Message: ----------- Added missing package. Modified Paths: -------------- trunk/core/descriptors/org.classpath.ext.core.xml Modified: trunk/core/descriptors/org.classpath.ext.core.xml =================================================================== --- trunk/core/descriptors/org.classpath.ext.core.xml 2007-02-03 20:51:24 UTC (rev 3104) +++ trunk/core/descriptors/org.classpath.ext.core.xml 2007-02-03 20:57:41 UTC (rev 3105) @@ -27,6 +27,7 @@ <export name="gnu.java.beans.encoder.*"/> <export name="gnu.java.beans.encoder.elements.*"/> <export name="gnu.java.lang.management.*"/> + <export name="gnu.java.lang.reflect.*"/> <export name="gnu.java.net.protocol.*"/> <export name="gnu.java.net.protocol.file.*"/> <export name="gnu.java.net.protocol.ftp.*"/> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-03 20:51:25
|
Revision: 3104 http://jnode.svn.sourceforge.net/jnode/?rev=3104&view=rev Author: lsantha Date: 2007-02-03 12:51:24 -0800 (Sat, 03 Feb 2007) Log Message: ----------- Fixed Desktop resizing. Modified Paths: -------------- trunk/gui/src/awt/org/jnode/awt/swingpeers/DesktopFrame.java Modified: trunk/gui/src/awt/org/jnode/awt/swingpeers/DesktopFrame.java =================================================================== --- trunk/gui/src/awt/org/jnode/awt/swingpeers/DesktopFrame.java 2007-02-03 20:51:00 UTC (rev 3103) +++ trunk/gui/src/awt/org/jnode/awt/swingpeers/DesktopFrame.java 2007-02-03 20:51:24 UTC (rev 3104) @@ -21,12 +21,7 @@ package org.jnode.awt.swingpeers; -import java.awt.AWTEvent; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.DefaultFocusTraversalPolicy; -import java.awt.Dimension; -import java.awt.Graphics; +import java.awt.*; import java.awt.image.BufferedImage; import java.beans.PropertyVetoException; @@ -97,6 +92,8 @@ public void adjustDesktopSize(int width, int height) { setSize(width, height); + VMAwtAPI.invalidateTree(this); + validateTree(); } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-03 20:51:03
|
Revision: 3103 http://jnode.svn.sourceforge.net/jnode/?rev=3103&view=rev Author: lsantha Date: 2007-02-03 12:51:00 -0800 (Sat, 03 Feb 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/awt/Component.java trunk/core/src/classpath/java/java/awt/Container.java trunk/core/src/classpath/java/java/awt/Window.java Modified: trunk/core/src/classpath/java/java/awt/Component.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Component.java 2007-02-03 18:44:48 UTC (rev 3102) +++ trunk/core/src/classpath/java/java/awt/Component.java 2007-02-03 20:51:00 UTC (rev 3103) @@ -1180,14 +1180,7 @@ */ public Font getFont() { - Font f = font; - if (f != null) - return f; - - Component p = parent; - if (p != null) - return p.getFont(); - return null; + return getFontImpl(); } /** @@ -1223,19 +1216,45 @@ * * @see #getFont() */ - public void setFont(Font newFont) + public void setFont(Font f) { - if((newFont != null && (font == null || !font.equals(newFont))) - || newFont == null) + Font oldFont; + Font newFont; + // Synchronize on the tree because getFontImpl() relies on the hierarchy + // not beeing changed. + synchronized (getTreeLock()) { - Font oldFont = font; - font = newFont; - if (peer != null) - peer.setFont(font); + // Synchronize on this here to guarantee thread safety wrt to the + // property values. + synchronized (this) + { + oldFont = font; + font = f; + newFont = f; + } + // Create local variable here for thread safety. + ComponentPeer p = peer; + if (p != null) + { + // The peer receives the real font setting, which can depend on + // the parent font when this component's font has been set to null. + f = getFont(); + if (f != null) + { + p.setFont(f); + peerFont = f; + } + } + } + + // Fire property change event. firePropertyChange("font", oldFont, newFont); + + // Invalidate when necessary as font changes can change the size of the + // component. + if (valid) invalidate(); } - } /** * Tests if the font was explicitly set, or just inherited from the parent. @@ -1521,55 +1540,50 @@ */ public void reshape(int x, int y, int width, int height) { + // We need to lock the tree here, otherwise we risk races and + // inconsistencies. + synchronized (getTreeLock()) + { int oldx = this.x; int oldy = this.y; int oldwidth = this.width; int oldheight = this.height; - if (this.x == x && this.y == y && this.width == width - && this.height == height) - return; + boolean resized = oldwidth != width || oldheight != height; + boolean moved = oldx != x || oldy != y; - invalidate(); - + if (resized || moved) + { + // Update the fields. this.x = x; this.y = y; this.width = width; this.height = height; - if (peer != null) - peer.setBounds (x, y, width, height); - // Erase old bounds and repaint new bounds for lightweights. - if (isLightweight() && isShowing()) + if (peer != null) { - if (parent != null) - { - Rectangle oldBounds = new Rectangle(oldx, oldy, oldwidth, - oldheight); - Rectangle newBounds = new Rectangle(x, y, width, height); - Rectangle destroyed = oldBounds.union(newBounds); - if (!destroyed.isEmpty()) - parent.repaint(0, destroyed.x, destroyed.y, destroyed.width, - destroyed.height); + peer.setBounds (x, y, width, height); + if (resized) + invalidate(); + if (parent != null && parent.valid) + parent.invalidate(); } - } - // Only post event if this component is visible and has changed size. - if (isShowing () - && (oldx != x || oldy != y)) + // Send some events to interested listeners. + notifyReshape(resized, moved); + + // Repaint this component and the parent if appropriate. + if (parent != null && peer instanceof LightweightPeer + && isShowing()) { - ComponentEvent ce = new ComponentEvent(this, - ComponentEvent.COMPONENT_MOVED); - getToolkit().getSystemEventQueue().postEvent(ce); + // The parent repaints the area that we occupied before. + parent.repaint(oldx, oldy, oldwidth, oldheight); + // This component repaints the area that we occupy now. + repaint(); } - if (isShowing () - && (oldwidth != width || oldheight != height)) - { - ComponentEvent ce = new ComponentEvent(this, - ComponentEvent.COMPONENT_RESIZED); - getToolkit().getSystemEventQueue().postEvent(ce); } } + } /** * Sends notification to interested listeners about resizing and/or moving @@ -1804,15 +1818,10 @@ */ public Dimension preferredSize() { - if (prefSize == null) - { - if (peer == null) - prefSize = minimumSize(); - else - prefSize = peer.getPreferredSize(); + // Create a new Dimension object, so that the application doesn't mess + // with the actual values. + return new Dimension(preferredSizeImpl()); } - return prefSize; - } /** * The actual calculation is pulled out of preferredSize() so that @@ -1895,10 +1904,9 @@ */ public Dimension minimumSize() { - if (minSize == null) - minSize = (peer != null ? peer.getMinimumSize() - : new Dimension(width, height)); - return minSize; + // Create a new Dimension object, so that the application doesn't mess + // with the actual values. + return new Dimension(minimumSizeImpl()); } /** @@ -1939,7 +1947,7 @@ */ public Dimension getMaximumSize() { - return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); + return new Dimension(maximumSizeImpl()); } /** @@ -2854,10 +2862,13 @@ */ public synchronized void addComponentListener(ComponentListener listener) { - componentListener = AWTEventMulticaster.add(componentListener, listener); - if (componentListener != null) - enableEvents(AWTEvent.COMPONENT_EVENT_MASK); + if (listener != null) + { + componentListener = AWTEventMulticaster.add(componentListener, + listener); + newEventsOnly = true; } + } /** * Removes the specified listener from the component. This is harmless if @@ -2902,10 +2913,12 @@ */ public synchronized void addFocusListener(FocusListener listener) { + if (listener != null) + { focusListener = AWTEventMulticaster.add(focusListener, listener); - if (focusListener != null) - enableEvents(AWTEvent.FOCUS_EVENT_MASK); + newEventsOnly = true; } + } /** * Removes the specified listener from the component. This is harmless if @@ -2949,10 +2962,21 @@ */ public synchronized void addHierarchyListener(HierarchyListener listener) { - hierarchyListener = AWTEventMulticaster.add(hierarchyListener, listener); - if (hierarchyListener != null) - enableEvents(AWTEvent.HIERARCHY_EVENT_MASK); + if (listener != null) + { + hierarchyListener = AWTEventMulticaster.add(hierarchyListener, + listener); + newEventsOnly = true; + // Need to lock the tree, otherwise we might end up inconsistent. + synchronized (getTreeLock()) + { + numHierarchyListeners++; + if (parent != null) + parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, + 1); } + } + } /** * Removes the specified listener from the component. This is harmless if @@ -2967,7 +2991,16 @@ public synchronized void removeHierarchyListener(HierarchyListener listener) { hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, listener); + + // Need to lock the tree, otherwise we might end up inconsistent. + synchronized (getTreeLock()) + { + numHierarchyListeners--; + if (parent != null) + parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, + -1); } + } /** * Returns an array of all specified listeners registered on this component. @@ -2998,11 +3031,22 @@ public synchronized void addHierarchyBoundsListener(HierarchyBoundsListener listener) { + if (listener != null) + { hierarchyBoundsListener = AWTEventMulticaster.add(hierarchyBoundsListener, listener); - if (hierarchyBoundsListener != null) - enableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK); + newEventsOnly = true; + + // Need to lock the tree, otherwise we might end up inconsistent. + synchronized (getTreeLock()) + { + numHierarchyBoundsListeners++; + if (parent != null) + parent.updateHierarchyListenerCount + (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1); } + } + } /** * Removes the specified listener from the component. This is harmless if @@ -3019,7 +3063,17 @@ { hierarchyBoundsListener = AWTEventMulticaster.remove(hierarchyBoundsListener, listener); + + // Need to lock the tree, otherwise we might end up inconsistent. + synchronized (getTreeLock()) + { + numHierarchyBoundsListeners--; + if (parent != null) + parent.updateHierarchyListenerCount + (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, + -1); } + } /** * Returns an array of all specified listeners registered on this component. @@ -3083,10 +3137,12 @@ */ public synchronized void addKeyListener(KeyListener listener) { + if (listener != null) + { keyListener = AWTEventMulticaster.add(keyListener, listener); - if (keyListener != null) - enableEvents(AWTEvent.KEY_EVENT_MASK); + newEventsOnly = true; } + } /** * Removes the specified listener from the component. This is harmless if @@ -3130,10 +3186,12 @@ */ public synchronized void addMouseListener(MouseListener listener) { + if (listener != null) + { mouseListener = AWTEventMulticaster.add(mouseListener, listener); - if (mouseListener != null) - enableEvents(AWTEvent.MOUSE_EVENT_MASK); + newEventsOnly = true; } + } /** * Removes the specified listener from the component. This is harmless if @@ -3177,10 +3235,13 @@ */ public synchronized void addMouseMotionListener(MouseMotionListener listener) { - mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, listener); - if (mouseMotionListener != null) - enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK); + if (listener != null) + { + mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, + listener); + newEventsOnly = true; } + } /** * Removes the specified listener from the component. This is harmless if @@ -3226,10 +3287,13 @@ */ public synchronized void addMouseWheelListener(MouseWheelListener listener) { - mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener, listener); - if (mouseWheelListener != null) - enableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK); + if (listener != null) + { + mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener, + listener); + newEventsOnly = true; } + } /** * Removes the specified listener from the component. This is harmless if @@ -3276,10 +3340,13 @@ */ public synchronized void addInputMethodListener(InputMethodListener listener) { - inputMethodListener = AWTEventMulticaster.add(inputMethodListener, listener); - if (inputMethodListener != null) - enableEvents(AWTEvent.INPUT_METHOD_EVENT_MASK); + if (listener != null) + { + inputMethodListener = AWTEventMulticaster.add(inputMethodListener, + listener); + newEventsOnly = true; } + } /** * Removes the specified listener from the component. This is harmless if @@ -3445,19 +3512,42 @@ */ protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent) { + AWTEvent coalesced = null; switch (existingEvent.id) { case MouseEvent.MOUSE_MOVED: case MouseEvent.MOUSE_DRAGGED: // Just drop the old (intermediate) event and return the new one. - return newEvent; + MouseEvent me1 = (MouseEvent) existingEvent; + MouseEvent me2 = (MouseEvent) newEvent; + if (me1.getModifiers() == me2.getModifiers()) + coalesced = newEvent; + break; case PaintEvent.PAINT: case PaintEvent.UPDATE: - return coalescePaintEvents((PaintEvent) existingEvent, - (PaintEvent) newEvent); + // For heavyweights the EventQueue should ask the peer. + if (peer == null || peer instanceof LightweightPeer) + { + PaintEvent pe1 = (PaintEvent) existingEvent; + PaintEvent pe2 = (PaintEvent) newEvent; + Rectangle r1 = pe1.getUpdateRect(); + Rectangle r2 = pe2.getUpdateRect(); + if (r1.contains(r2)) + coalesced = existingEvent; + else if (r2.contains(r1)) + coalesced = newEvent; + } + else + { + // Replace the event and let the heavyweight figure out the expanding + // of the repaint area. + coalesced = newEvent; + } + break; default: - return null; + coalesced = null; } + return coalesced; } /** Modified: trunk/core/src/classpath/java/java/awt/Container.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Container.java 2007-02-03 18:44:48 UTC (rev 3102) +++ trunk/core/src/classpath/java/java/awt/Container.java 2007-02-03 20:51:00 UTC (rev 3103) @@ -87,9 +87,7 @@ Component[] component; LayoutManager layoutMgr; - Dimension maxSize; - - /* + /** * @since 1.4 */ boolean focusCycleRoot; @@ -1912,16 +1910,18 @@ */ void dispatchEventImpl(AWTEvent e) { - boolean dispatched = - LightweightDispatcher.getInstance().dispatchEvent(e); - if (! dispatched) + LightweightDispatcher dispatcher = LightweightDispatcher.getInstance(); + if (! isLightweight() && dispatcher.dispatchEvent(e)) { - if ((e.id <= ContainerEvent.CONTAINER_LAST - && e.id >= ContainerEvent.CONTAINER_FIRST) - && (containerListener != null - || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)) - processEvent(e); + // Some lightweight descendent got this event dispatched. Consume + // it and let the peer handle it. + e.consume(); + ComponentPeer p = peer; + if (p != null) + p.handleEvent(e); + } else + { super.dispatchEventImpl(e); } } Modified: trunk/core/src/classpath/java/java/awt/Window.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Window.java 2007-02-03 18:44:48 UTC (rev 3102) +++ trunk/core/src/classpath/java/java/awt/Window.java 2007-02-03 20:51:00 UTC (rev 3103) @@ -286,8 +286,6 @@ { synchronized (getTreeLock()) { - if (parent != null && ! parent.isDisplayable()) - parent.addNotify(); if (peer == null) addNotify(); @@ -529,8 +527,12 @@ */ public synchronized void addWindowListener(WindowListener listener) { + if (listener != null) + { + newEventsOnly = true; windowListener = AWTEventMulticaster.add(windowListener, listener); } + } /** * Removes the specified listener from the list of @@ -586,9 +588,14 @@ */ public void addWindowFocusListener (WindowFocusListener wfl) { - windowFocusListener = AWTEventMulticaster.add (windowFocusListener, wfl); + if (wfl != null) + { + newEventsOnly = true; + windowFocusListener = AWTEventMulticaster.add (windowFocusListener, + wfl); } - + } + /** * Adds the specified listener to this window. * @@ -596,9 +603,14 @@ */ public void addWindowStateListener (WindowStateListener wsl) { - windowStateListener = AWTEventMulticaster.add (windowStateListener, wsl); + if (wsl != null) + { + newEventsOnly = true; + windowStateListener = AWTEventMulticaster.add (windowStateListener, + wsl); } - + } + /** * Removes the specified listener from this window. */ @@ -636,17 +648,11 @@ void dispatchEventImpl(AWTEvent e) { - // Make use of event id's in order to avoid multiple instanceof tests. - if (e.id <= WindowEvent.WINDOW_LAST - && e.id >= WindowEvent.WINDOW_FIRST - && (windowListener != null - || windowFocusListener != null - || windowStateListener != null - || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)) - processEvent(e); - else if (e.id == ComponentEvent.COMPONENT_RESIZED) + if (e.getID() == ComponentEvent.COMPONENT_RESIZED) + { + invalidate(); validate (); - else + } super.dispatchEventImpl(e); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-03 18:44:50
|
Revision: 3102 http://jnode.svn.sourceforge.net/jnode/?rev=3102&view=rev Author: lsantha Date: 2007-02-03 10:44:48 -0800 (Sat, 03 Feb 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/awt/Component.java trunk/core/src/classpath/java/java/awt/Container.java trunk/core/src/classpath/java/java/awt/Window.java Modified: trunk/core/src/classpath/java/java/awt/Component.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Component.java 2007-02-03 15:05:27 UTC (rev 3101) +++ trunk/core/src/classpath/java/java/awt/Component.java 2007-02-03 18:44:48 UTC (rev 3102) @@ -971,18 +971,40 @@ // case lightweight components are not initially painted -- // Container.paint first calls isShowing () before painting itself // and its children. - if(!isVisible()) + if(! visible) { - this.visible = true; + // Need to lock the tree here to avoid races and inconsistencies. + synchronized (getTreeLock()) + { + visible = true; // Avoid NullPointerExceptions by creating a local reference. ComponentPeer currentPeer=peer; if (currentPeer != null) + { currentPeer.show(); + // Fire HierarchyEvent. + fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, + this, parent, + HierarchyEvent.SHOWING_CHANGED); + // The JDK repaints the component before invalidating the parent. // So do we. - if (isShowing() && isLightweight()) + if (peer instanceof LightweightPeer) repaint(); + } + + // Only post an event if this component actually has a listener + // or has this event explicitly enabled. + if (componentListener != null + || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0) + { + ComponentEvent ce = + new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN); + getToolkit().getSystemEventQueue().postEvent(ce); + } + } + // Invalidate the parent if we have one. The component itself must // not be invalidated. We also avoid NullPointerException with // a local reference here. @@ -990,9 +1012,6 @@ if (currentParent != null) currentParent.invalidate(); - ComponentEvent ce = - new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN); - getToolkit().getSystemEventQueue().postEvent(ce); } } @@ -1018,29 +1037,47 @@ */ public void hide() { - if (isVisible()) + if (visible) { + // Need to lock the tree here to avoid races and inconsistencies. + synchronized (getTreeLock()) + { + visible = false; + // Avoid NullPointerExceptions by creating a local reference. ComponentPeer currentPeer=peer; if (currentPeer != null) - currentPeer.setVisible(false); - boolean wasShowing = isShowing(); - this.visible = false; + { + currentPeer.hide(); - // The JDK repaints the component before invalidating the parent. - // So do we. - if (wasShowing) + // Fire hierarchy event. + fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, + this, parent, + HierarchyEvent.SHOWING_CHANGED); + // The JDK repaints the component before invalidating the + // parent. So do we. This only applies for lightweights. + if (peer instanceof LightweightPeer) repaint(); - // Invalidate the parent if we have one. The component itself must + } + + // Only post an event if this component actually has a listener + // or has this event explicitly enabled. + if (componentListener != null + || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0) + { + ComponentEvent ce = + new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN); + getToolkit().getSystemEventQueue().postEvent(ce); + } + } + + // Invalidate the parent if we have one. The component itself need // not be invalidated. We also avoid NullPointerException with // a local reference here. Container currentParent = parent; if (currentParent != null) currentParent.invalidate(); - ComponentEvent ce = - new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN); - getToolkit().getSystemEventQueue().postEvent(ce); } } @@ -3935,19 +3972,38 @@ */ public void addNotify() { + // We need to lock the tree here to avoid races and inconsistencies. + synchronized (getTreeLock()) + { if (peer == null) peer = getToolkit().createComponent(this); else if (parent != null && parent.isLightweight()) new HeavyweightInLightweightListener(parent); - /* Now that all the children has gotten their peers, we should - have the event mask needed for this component and its - lightweight subcomponents. */ + // Now that all the children has gotten their peers, we should + // have the event mask needed for this component and its + //lightweight subcomponents. peer.setEventMask(eventMask); - /* We do not invalidate here, but rather leave that job up to - the peer. For efficiency, the peer can choose not to - invalidate if it is happy with the current dimensions, - etc. */ + + // We used to leave the invalidate() to the peer. However, I put it + // back here for 2 reasons: 1) The RI does call invalidate() from + // addNotify(); 2) The peer shouldn't be bother with validation too + // much. + invalidate(); + + if (dropTarget != null) + dropTarget.addNotify(peer); + + // Fetch the peerFont for later installation in validate(). + peerFont = getFont(); + + // Notify hierarchy listeners. + long flags = HierarchyEvent.DISPLAYABILITY_CHANGED; + if (isHierarchyVisible()) + flags |= HierarchyEvent.SHOWING_CHANGED; + fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent, + flags); } + } /** * Called to inform this component is has been removed from its @@ -3960,6 +4016,9 @@ */ public void removeNotify() { + // We need to lock the tree here to avoid races and inconsistencies. + synchronized (getTreeLock()) + { // We null our peer field before disposing of it, such that if we're // not the event dispatch thread and the dispatch thread is awoken by // the dispose call, there will be no race checking the peer's null @@ -3967,12 +4026,21 @@ ComponentPeer tmp = peer; peer = null; + peerFont = null; if (tmp != null) { tmp.hide(); tmp.dispose(); } + + // Notify hierarchy listeners. + long flags = HierarchyEvent.DISPLAYABILITY_CHANGED; + if (isHierarchyVisible()) + flags |= HierarchyEvent.SHOWING_CHANGED; + fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent, + flags); } + } /** * AWT 1.0 GOT_FOCUS event handler. This method is meant to be Modified: trunk/core/src/classpath/java/java/awt/Container.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Container.java 2007-02-03 15:05:27 UTC (rev 3101) +++ trunk/core/src/classpath/java/java/awt/Container.java 2007-02-03 18:44:48 UTC (rev 3102) @@ -39,7 +39,6 @@ package java.awt; -import java.awt.event.ComponentListener; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.awt.event.HierarchyEvent; @@ -90,12 +89,7 @@ Dimension maxSize; - /** - * Keeps track if the Container was cleared during a paint/update. - */ - private boolean backCleared; - - /** + /* * @since 1.4 */ boolean focusCycleRoot; @@ -333,24 +327,7 @@ // we are. if (comp.parent != null) comp.parent.remove(comp); - comp.parent = this; - if (peer != null) - { - // Notify the component that it has a new parent. - comp.addNotify(); - - if (comp.isLightweight ()) - { - enableEvents (comp.eventMask); - if (!isLightweight ()) - enableEvents (AWTEvent.PAINT_EVENT_MASK); - } - } - - // Invalidate the layout of the added component and its ancestors. - comp.invalidate(); - if (component == null) component = new Component[4]; // FIXME, better initial size? @@ -374,6 +351,31 @@ ++ncomponents; } + // Give the new component a parent. + comp.parent = this; + + // Update the counter for Hierarchy(Bounds)Listeners. + int childHierarchyListeners = comp.numHierarchyListeners; + if (childHierarchyListeners > 0) + updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, + childHierarchyListeners); + int childHierarchyBoundsListeners = comp.numHierarchyBoundsListeners; + if (childHierarchyBoundsListeners > 0) + updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, + childHierarchyListeners); + + // Invalidate the layout of this container. + if (valid) + invalidate(); + + // Create the peer _after_ the component has been added, so that + // the peer gets to know about the component hierarchy. + if (peer != null) + { + // Notify the component that it has a new parent. + comp.addNotify(); + } + // Notify the layout manager. if (layoutMgr != null) { @@ -394,14 +396,20 @@ // Also, the event was posted to the event queue. A Mauve test shows // that this event is not delivered using the event queue and it is // also sent when the container is not showing. + if (containerListener != null + || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) + { ContainerEvent ce = new ContainerEvent(this, ContainerEvent.COMPONENT_ADDED, comp); - ContainerListener[] listeners = getContainerListeners(); - for (int i = 0; i < listeners.length; i++) - listeners[i].componentAdded(ce); + dispatchEvent(ce); } + + // Notify hierarchy listeners. + comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp, + this, HierarchyEvent.PARENT_CHANGED); } + } /** * Removes the component at the specified index from this container. @@ -412,33 +420,48 @@ { synchronized (getTreeLock ()) { + if (index < 0 || index >= ncomponents) + throw new ArrayIndexOutOfBoundsException(); + Component r = component[index]; + if (peer != null) + r.removeNotify(); - ComponentListener[] list = r.getComponentListeners(); - for (int j = 0; j < list.length; j++) - r.removeComponentListener(list[j]); + if (layoutMgr != null) + layoutMgr.removeLayoutComponent(r); - r.removeNotify(); + // Update the counter for Hierarchy(Bounds)Listeners. + int childHierarchyListeners = r.numHierarchyListeners; + if (childHierarchyListeners > 0) + updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, + -childHierarchyListeners); + int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners; + if (childHierarchyBoundsListeners > 0) + updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, + -childHierarchyListeners); + r.parent = null; + System.arraycopy(component, index + 1, component, index, ncomponents - index - 1); component[--ncomponents] = null; + if (valid) invalidate(); - if (layoutMgr != null) - layoutMgr.removeLayoutComponent(r); - - r.parent = null; - - if (isShowing ()) + if (containerListener != null + || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) { // Post event to notify of removing the component. ContainerEvent ce = new ContainerEvent(this, ContainerEvent.COMPONENT_REMOVED, r); - getToolkit().getSystemEventQueue().postEvent(ce); + dispatchEvent(ce); } + + // Notify hierarchy listeners. + r.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, + this, HierarchyEvent.PARENT_CHANGED); } } @@ -477,14 +500,13 @@ // super.removeAll() ). // By doing it this way, user code cannot prevent the correct // removal of components. - for ( int index = 0; index < ncomponents; index++) + while (ncomponents > 0) { - Component r = component[index]; + ncomponents--; + Component r = component[ncomponents]; + component[ncomponents] = null; - ComponentListener[] list = r.getComponentListeners(); - for (int j = 0; j < list.length; j++) - r.removeComponentListener(list[j]); - + if (peer != null) r.removeNotify(); if (layoutMgr != null) @@ -492,21 +514,37 @@ r.parent = null; - if (isShowing ()) + // Send ContainerEvent if necessary. + if (containerListener != null + || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) { // Post event to notify of removing the component. ContainerEvent ce = new ContainerEvent(this, ContainerEvent.COMPONENT_REMOVED, r); - - getToolkit().getSystemEventQueue().postEvent(ce); + dispatchEvent(ce); } - } - + + // Update the counter for Hierarchy(Bounds)Listeners. + int childHierarchyListeners = r.numHierarchyListeners; + if (childHierarchyListeners > 0) + updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, + -childHierarchyListeners); + int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners; + if (childHierarchyBoundsListeners > 0) + updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, + -childHierarchyListeners); + + + // Send HierarchyEvent if necessary. + fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this, + HierarchyEvent.PARENT_CHANGED); + + } + + if (valid) invalidate(); - - ncomponents = 0; } } @@ -571,11 +609,20 @@ */ public void validate() { + ComponentPeer p = peer; + if (! valid && p != null) + { + ContainerPeer cPeer = null; + if (p instanceof ContainerPeer) + cPeer = (ContainerPeer) peer; synchronized (getTreeLock ()) { - if (! isValid() && peer != null) - { + if (cPeer != null) + cPeer.beginValidate(); validateTree(); + valid = true; + if (cPeer != null) + cPeer.endValidate(); } } } @@ -585,19 +632,18 @@ */ void invalidateTree() { - super.invalidate(); // Clean cached layout state. + synchronized (getTreeLock()) + { for (int i = 0; i < ncomponents; i++) { Component comp = component[i]; - comp.invalidate(); if (comp instanceof Container) ((Container) comp).invalidateTree(); + else if (comp.valid) + comp.invalidate(); } - - if (layoutMgr != null && layoutMgr instanceof LayoutManager2) - { - LayoutManager2 lm2 = (LayoutManager2) layoutMgr; - lm2.invalidateLayout(this); + if (valid) + invalidate(); } } @@ -607,60 +653,52 @@ */ protected void validateTree() { - if (valid) - return; - + if (!valid) + { ContainerPeer cPeer = null; - if (peer != null && ! (peer instanceof LightweightPeer)) + if (peer instanceof ContainerPeer) { cPeer = (ContainerPeer) peer; - cPeer.beginValidate(); + cPeer.beginLayout(); } - for (int i = 0; i < ncomponents; ++i) - { - Component comp = component[i]; - - if (comp.getPeer () == null) - comp.addNotify(); - } - doLayout (); for (int i = 0; i < ncomponents; ++i) { Component comp = component[i]; - if (! comp.isValid()) + if (comp instanceof Container && ! (comp instanceof Window) + && ! comp.valid) { - if (comp instanceof Container) - { ((Container) comp).validateTree(); } else { - component[i].validate(); + comp.validate(); } } + + if (cPeer != null) + { + cPeer = (ContainerPeer) peer; + cPeer.endLayout(); } + } /* children will call invalidate() when they are layed out. It is therefore important that valid is not set to true until after the children have been layed out. */ valid = true; - if (cPeer != null) - cPeer.endValidate(); } public void setFont(Font f) { - if( (f != null && (font == null || !font.equals(f))) - || f == null) + Font oldFont = getFont(); + super.setFont(f); + Font newFont = getFont(); + if (newFont != oldFont && (oldFont == null || ! oldFont.equals(newFont))) { - super.setFont(f); - // FIXME: Although it might make more sense to invalidate only - // those children whose font == null, Sun invalidates all children. - // So we'll do the same. invalidateTree(); } } @@ -922,8 +960,13 @@ */ public synchronized void addContainerListener(ContainerListener listener) { - containerListener = AWTEventMulticaster.add(containerListener, listener); + if (listener != null) + { + containerListener = AWTEventMulticaster.add(containerListener, + listener); + newEventsOnly = true; } + } /** * Removes the specified container listener from this object's list of @@ -1853,6 +1896,7 @@ bounds.height); try { + g2.setFont(comp.getFont()); visitor.visit(comp, g2); } finally @@ -2053,15 +2097,9 @@ for (int i = ncomponents; --i >= 0; ) { component[i].addNotify(); - if (component[i].isLightweight ()) - { - enableEvents(component[i].eventMask); - if (peer != null && !isLightweight ()) - enableEvents (AWTEvent.PAINT_EVENT_MASK); } } } - } /** * Deserialize this Container: Modified: trunk/core/src/classpath/java/java/awt/Window.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Window.java 2007-02-03 15:05:27 UTC (rev 3101) +++ trunk/core/src/classpath/java/java/awt/Window.java 2007-02-03 18:44:48 UTC (rev 3102) @@ -393,11 +393,17 @@ component[i].removeNotify(); this.removeNotify(); - // Post a WINDOW_CLOSED event. - WindowEvent we = new WindowEvent(this, WindowEvent.WINDOW_CLOSED); - getToolkit().getSystemEventQueue().postEvent(we); + // Post WINDOW_CLOSED from here. + if (windowListener != null + || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0) + { + WindowEvent ev = new WindowEvent(this, + WindowEvent.WINDOW_CLOSED); + Toolkit tk = Toolkit.getDefaultToolkit(); + tk.getSystemEventQueue().postEvent(ev); } } + } /** * Sends this window to the back so that all other windows display in This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-02-03 15:05:36
|
Revision: 3101 http://jnode.svn.sourceforge.net/jnode/?rev=3101&view=rev Author: lsantha Date: 2007-02-03 07:05:27 -0800 (Sat, 03 Feb 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/awt/Component.java trunk/core/src/classpath/java/java/awt/Container.java trunk/core/src/classpath/java/java/awt/Window.java Modified: trunk/core/src/classpath/java/java/awt/Component.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Component.java 2007-01-31 21:51:44 UTC (rev 3100) +++ trunk/core/src/classpath/java/java/awt/Component.java 2007-02-03 15:05:27 UTC (rev 3101) @@ -581,7 +581,7 @@ transient ComponentPeer peer; /** The preferred component orientation. */ - transient ComponentOrientation orientation = ComponentOrientation.UNKNOWN; + transient ComponentOrientation componentOrientation = ComponentOrientation.UNKNOWN; /** * The associated graphics configuration. @@ -748,17 +748,24 @@ */ public Toolkit getToolkit() { - if (peer != null) + // Only heavyweight peers can handle this. + ComponentPeer p = peer; + Component comp = this; + while (p instanceof LightweightPeer) { - Toolkit tk = peer.getToolkit(); - if (tk != null) - return tk; + comp = comp.parent; + p = comp == null ? null : comp.peer; } - // Get toolkit for lightweight component. - if (parent != null) - return parent.getToolkit(); - return Toolkit.getDefaultToolkit(); + + Toolkit tk = null; + if (p != null) + { + tk = peer.getToolkit(); } + if (tk == null) + tk = Toolkit.getDefaultToolkit(); + return tk; + } /** * Tests whether or not this component is valid. A invalid component needs @@ -770,7 +777,9 @@ */ public boolean isValid() { - return valid; + // Tests show that components are invalid as long as they are not showing, even after validate() + // has been called on them. + return peer != null && valid; } /** @@ -814,10 +823,8 @@ */ public boolean isShowing() { - if (! visible || peer == null) - return false; - - return parent == null ? false : parent.isShowing(); + Component par = parent; + return visible && peer != null && (par == null || par.isShowing()); } /** @@ -856,10 +863,18 @@ */ public void enable() { - this.enabled = true; - if (peer != null) - peer.setEnabled (true); + if (! enabled) + { + // Need to lock the tree here, because the peers are involved. + synchronized (getTreeLock()) + { + enabled = true; + ComponentPeer p = peer; + if (p != null) + p.enable(); } + } + } /** * Enables or disables this component. @@ -883,10 +898,18 @@ */ public void disable() { - this.enabled = false; - if (peer != null) - peer.setEnabled (false); + if (enabled) + { + // Need to lock the tree here, because the peers are involved. + synchronized (getTreeLock()) + { + enabled = false; + ComponentPeer p = peer; + if (p != null) + p.disable(); } + } + } /** * Checks if this image is painted to an offscreen image buffer that is @@ -1130,11 +1153,36 @@ return null; } - /** + /** + * Implementation of getFont(). This is pulled out of getFont() to prevent + * client programs from overriding this. + * + * @return the font of this component + */ + private final Font getFontImpl() + { + Font f = font; + if (f == null) + { + Component p = parent; + if (p != null) + f = p.getFontImpl(); + else + { + // It is important to return null here and not some kind of default + // font, otherwise the Swing UI would not install its fonts because + // it keeps non-UIResource fonts. + f = null; + } + } + return f; + } + + /** * Sets the font for this component to the specified font. This is a bound * property. * - * @param newFont the new font for this component + * @param f the new font for this component * * @see #getFont() */ @@ -1729,11 +1777,39 @@ return prefSize; } + /** + * The actual calculation is pulled out of preferredSize() so that + * we can call it from Container.preferredSize() and avoid creating a + * new intermediate Dimension object. + * + * @return the preferredSize of the component + */ + Dimension preferredSizeImpl() + { + Dimension size = prefSize; + // Try to use a cached value. + if (size == null || !(valid || prefSizeSet)) + { + // We need to lock here, because the calculation depends on the + // component structure not changing. + synchronized (getTreeLock()) + { + ComponentPeer p = peer; + if (p != null) + size = peer.preferredSize(); + else + size = minimumSizeImpl(); + } + } + return size; + } + /** * Returns the component's minimum size. * * @return the component's minimum size * @see #getPreferredSize() + * @see #setMinimumSize(Dimension) * @see LayoutManager */ public Dimension getMinimumSize() @@ -1937,8 +2013,33 @@ */ public void validate() { + if (! valid) + { + // Synchronize on the tree here as this might change the layout + // of the hierarchy. + synchronized (getTreeLock()) + { + // Create local variables for thread safety. + ComponentPeer p = peer; + if (p != null) + { + // Possibly update the peer's font. + Font newFont = getFont(); + Font oldFont = peerFont; + // Only update when the font really changed. + if (newFont != oldFont + && (oldFont == null || ! oldFont.equals(newFont))) + { + p.setFont(newFont); + peerFont = newFont; + } + // Let the peer perform any layout. + p.layout(); + } + } valid = true; } + } /** * Invalidates this component and all of its parent components. This will @@ -1947,12 +2048,26 @@ */ public void invalidate() { + // Need to lock here, to avoid races and other ugly stuff when doing + // layout or structure changes in other threads. + synchronized (getTreeLock()) + { + // Invalidate. valid = false; - prefSize = null; + + // Throw away cached layout information. + if (! minSizeSet) minSize = null; + if (! prefSizeSet) + prefSize = null; + if (! maxSizeSet) + maxSize = null; + + // Also invalidate the parent, if it hasn't already been invalidated. if (parent != null && parent.isValid()) parent.invalidate(); } + } /** * Returns a graphics object for this component. Returns <code>null</code> @@ -1998,10 +2113,18 @@ */ public FontMetrics getFontMetrics(Font font) { - return peer == null ? getToolkit().getFontMetrics(font) - : peer.getFontMetrics(font); + ComponentPeer p = peer; + Component comp = this; + while (p instanceof LightweightPeer) + { + comp = comp.parent; + p = comp == null ? null : comp.peer; } + return p == null ? getToolkit().getFontMetrics(font) + : p.getFontMetrics(font); + } + /** * Sets the cursor for this component to the specified cursor. The cursor * is displayed when the point is contained by the component, and the @@ -2018,10 +2141,20 @@ public void setCursor(Cursor cursor) { this.cursor = cursor; - if (peer != null) - peer.setCursor(cursor); + + // Only heavyweight peers handle this. + ComponentPeer p = peer; + Component comp = this; + while (p instanceof LightweightPeer) + { + comp = comp.parent; + p = comp == null ? null : comp.peer; } + if (p != null) + p.setCursor(cursor); + } + /** * Returns the cursor for this component. If not set, this is inherited * from the parent, or from Cursor.getDefaultCursor(). @@ -2077,19 +2210,14 @@ */ public void update(Graphics g) { - // Tests show that the clearing of the background is only done in - // two cases: - // - If the component is lightweight (yes this is in contrast to the spec). - // or - // - If the component is a toplevel container. - if (isLightweight() || getParent() == null) - { - Rectangle clip = g.getClipBounds(); - if (clip == null) - g.clearRect(0, 0, width, height); - else - g.clearRect(clip.x, clip.y, clip.width, clip.height); - } + // Note 1: We used to clear the background here for lightweights and + // toplevel components. Tests show that this is not what the JDK does + // here. Note that there is some special handling and background + // clearing code in Container.update(Graphics). + + // Note 2 (for peer implementors): The JDK doesn't seem call update() for + // toplevel components, even when an UPDATE event is sent (as a result + // of repaint). paint(g); } @@ -2102,10 +2230,15 @@ */ public void paintAll(Graphics g) { - if (! visible) - return; + if (isShowing()) + { + validate(); + if (peer instanceof LightweightPeer) paint(g); + else + peer.paint(g); } + } /** * Repaint this entire component. The <code>update()</code> method @@ -2165,13 +2298,44 @@ */ public void repaint(long tm, int x, int y, int width, int height) { - if (isShowing()) + // The repaint() call has previously been delegated to + // {@link ComponentPeer.repaint()}. Testing on the JDK using some + // dummy peers show that this methods is never called. I think it makes + // sense to actually perform the tasks below here, since it's pretty + // much peer independent anyway, and makes sure only heavyweights are + // bothered by this. + ComponentPeer p = peer; + + // Let the nearest heavyweight parent handle repainting for lightweight + // components. + // We need to recursivly call repaint() on the parent here, since + // a (lightweight) parent component might have overridden repaint() + // to perform additional custom tasks. + + if (p instanceof LightweightPeer) { - ComponentPeer p = peer; - if (p != null) - p.repaint(tm, x, y, width, height); + // We perform some boundary checking to restrict the paint + // region to this component. + if (parent != null) + { + int px = this.x + Math.max(0, x); + int py = this.y + Math.max(0, y); + int pw = Math.min(this.width, width); + int ph = Math.min(this.height, height); + parent.repaint(tm, px, py, pw, ph); } } + else + { + // Now send an UPDATE event to the heavyweight component that we've found. + if (isVisible() && p != null && width > 0 && height > 0) + { + PaintEvent pe = new PaintEvent(this, PaintEvent.UPDATE, + new Rectangle(x, y, width, height)); + getToolkit().getSystemEventQueue().postEvent(pe); + } + } + } /** * Prints this component. This method is provided so that printing can be @@ -2196,6 +2360,8 @@ */ public void printAll(Graphics g) { + if( peer != null ) + peer.print( g ); paintAll(g); } @@ -2255,11 +2421,22 @@ */ public Image createImage(ImageProducer producer) { + // Only heavyweight peers can handle this. + ComponentPeer p = peer; + Component comp = this; + while (p instanceof LightweightPeer) + { + comp = comp.parent; + p = comp == null ? null : comp.peer; + } + // Sun allows producer to be null. - if (peer != null) - return peer.createImage(producer); + Image im; + if (p != null) + im = p.createImage(producer); else - return getToolkit().createImage(producer); + im = getToolkit().createImage(producer); + return im; } /** @@ -2275,11 +2452,18 @@ Image returnValue = null; if (!GraphicsEnvironment.isHeadless ()) { - if (isLightweight () && parent != null) - returnValue = parent.createImage (width, height); - else if (peer != null) - returnValue = peer.createImage (width, height); + // Only heavyweight peers can handle this. + ComponentPeer p = peer; + Component comp = this; + while (p instanceof LightweightPeer) + { + comp = comp.parent; + p = comp == null ? null : comp.peer; } + + if (p != null) + returnValue = p.createImage(width, height); + } return returnValue; } @@ -2294,11 +2478,21 @@ */ public VolatileImage createVolatileImage(int width, int height) { - if (peer != null) - return peer.createVolatileImage(width, height); - return null; + // Only heavyweight peers can handle this. + ComponentPeer p = peer; + Component comp = this; + while (p instanceof LightweightPeer) + { + comp = comp.parent; + p = comp == null ? null : comp.peer; } + VolatileImage im = null; + if (p != null) + im = p.createVolatileImage(width, height); + return im; + } + /** * Creates an image with the specified width and height for use in * double buffering. Headless environments do not support images. The image @@ -2315,11 +2509,21 @@ ImageCapabilities caps) throws AWTException { - if (peer != null) - return peer.createVolatileImage(width, height); - return null; + // Only heavyweight peers can handle this. + ComponentPeer p = peer; + Component comp = this; + while (p instanceof LightweightPeer) + { + comp = comp.parent; + p = comp == null ? null : comp.peer; } + VolatileImage im = null; + if (p != null) + im = peer.createVolatileImage(width, height); + return im; + } + /** * Prepares the specified image for rendering on this component. * @@ -2347,10 +2551,21 @@ public boolean prepareImage(Image image, int width, int height, ImageObserver observer) { - if (peer != null) - return peer.prepareImage(image, width, height, observer); + // Only heavyweight peers handle this. + ComponentPeer p = peer; + Component comp = this; + while (p instanceof LightweightPeer) + { + comp = comp.parent; + p = comp == null ? null : comp.peer; + } + + boolean retval; + if (p != null) + retval = p.prepareImage(image, width, height, observer); else - return getToolkit().prepareImage(image, width, height, observer); + retval = getToolkit().prepareImage(image, width, height, observer); + return retval; } /** @@ -2384,11 +2599,23 @@ public int checkImage(Image image, int width, int height, ImageObserver observer) { - if (peer != null) - return peer.checkImage(image, width, height, observer); - return getToolkit().checkImage(image, width, height, observer); + // Only heavyweight peers handle this. + ComponentPeer p = peer; + Component comp = this; + while (p instanceof LightweightPeer) + { + comp = comp.parent; + p = comp == null ? null : comp.peer; } + int retval; + if (p != null) + retval = p.checkImage(image, width, height, observer); + else + retval = getToolkit().checkImage(image, width, height, observer); + return retval; + } + /** * Sets whether paint messages delivered by the operating system should be * ignored. This does not affect messages from AWT, except for those @@ -4328,7 +4555,84 @@ return false; } - /** + /** + * Helper method for all 4 requestFocus variants. + * + * @param temporary indicates if the focus change is temporary + * @param focusWindow indicates if the window focus may be changed + * + * @return <code>false</code> if the request has been definitely denied, + * <code>true</code> otherwise + */ + private boolean requestFocusImpl(boolean temporary, boolean focusWindow) + { + boolean retval = false; + + // Don't try to focus non-focusable and non-visible components. + if (isFocusable() && isVisible()) + { + ComponentPeer myPeer = peer; + if (peer != null) + { + // Find Window ancestor and find out if we're showing while + // doing this. + boolean showing = true; + Component window = this; + while (! (window instanceof Window)) + { + if (! window.isVisible()) + showing = false; + window = window.parent; + } + // Don't allow focus when there is no window or the window + // is not focusable. + if (window != null && ((Window) window).isFocusableWindow() + && showing) + { + // Search for nearest heavy ancestor (including this + // component). + Component heavyweightParent = this; + while (heavyweightParent.peer instanceof LightweightPeer) + heavyweightParent = heavyweightParent.parent; + + // Don't allow focus on lightweight components without + // visible heavyweight ancestor + if (heavyweightParent != null && heavyweightParent.isVisible()) + { + // Don't allow focus when heavyweightParent has no peer. + myPeer = heavyweightParent.peer; + if (myPeer != null) + { + // Register lightweight focus request. + if (heavyweightParent != this) + { + KeyboardFocusManager + .addLightweightFocusRequest(heavyweightParent, + this); + } + + // Try to focus the component. + long time = EventQueue.getMostRecentEventTime(); + boolean success = myPeer.requestFocus(this, temporary, + focusWindow, + time); + if (! success) + { + // Dequeue key events if focus request failed. + KeyboardFocusManager kfm = + KeyboardFocusManager.getCurrentKeyboardFocusManager(); + kfm.dequeueKeyEvents(time, this); + } + retval = success; + } + } + } + } + } + return retval; + } + + /** * Transfers focus to the next component in the focus traversal * order, as though this were the current focus owner. * @@ -4972,10 +5276,9 @@ */ public void setComponentOrientation(ComponentOrientation o) { - if (o == null) - throw new NullPointerException(); - ComponentOrientation oldOrientation = orientation; - orientation = o; + + ComponentOrientation oldOrientation = componentOrientation; + componentOrientation = o; firePropertyChange("componentOrientation", oldOrientation, o); } @@ -4987,7 +5290,7 @@ */ public ComponentOrientation getComponentOrientation() { - return orientation; + return componentOrientation; } /** @@ -5137,7 +5440,7 @@ if ((mods & InputEvent.ALT_DOWN_MASK) != 0) oldMods |= Event.ALT_MASK; - if (e instanceof MouseEvent) + if (e instanceof MouseEvent && !ignoreOldMouseEvents()) { if (id == MouseEvent.MOUSE_PRESSED) oldID = Event.MOUSE_DOWN; @@ -5471,6 +5774,26 @@ } /** + * Returns <code>true</code> when this component and all of its ancestors + * are visible, <code>false</code> otherwise. + * + * @return <code>true</code> when this component and all of its ancestors + * are visible, <code>false</code> otherwise + */ + boolean isHierarchyVisible() + { + boolean visible = isVisible(); + Component comp = parent; + while (comp != null && visible) + { + comp = comp.parent; + if (comp != null) + visible = visible && comp.isVisible(); + } + return visible; + } + + /** * This method is used to implement transferFocus(). CHILD is the child * making the request. This is overridden by Container; when called for an * ordinary component there is no child and so we always return null. Modified: trunk/core/src/classpath/java/java/awt/Container.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Container.java 2007-01-31 21:51:44 UTC (rev 3100) +++ trunk/core/src/classpath/java/java/awt/Container.java 2007-02-03 15:05:27 UTC (rev 3101) @@ -215,10 +215,12 @@ */ public Insets insets() { - if (peer == null) - return new Insets (0, 0, 0, 0); - - return ((ContainerPeer) peer).getInsets (); + Insets i; + if (peer == null || peer instanceof LightweightPeer) + i = new Insets (0, 0, 0, 0); + else + i = ((ContainerPeer) peer).getInsets (); + return i; } /** @@ -527,6 +529,7 @@ public void setLayout(LayoutManager mgr) { layoutMgr = mgr; + if (valid) invalidate(); } @@ -681,22 +684,26 @@ */ public Dimension preferredSize() { - synchronized(treeLock) + Dimension size = prefSize; + // Try to return cached value if possible. + if (size == null || !(prefSizeSet || valid)) { - if(valid && prefSize != null) - return new Dimension(prefSize); - LayoutManager layout = getLayout(); - if (layout != null) + // Need to lock here. + synchronized (getTreeLock()) { - Dimension layoutSize = layout.preferredLayoutSize(this); - if(valid) - prefSize = layoutSize; - return new Dimension(layoutSize); - } + LayoutManager l = layoutMgr; + if (l != null) + prefSize = l.preferredLayoutSize(this); else - return super.preferredSize (); + prefSize = super.preferredSizeImpl(); + size = prefSize; } } + if (size != null) + return new Dimension(size); + else + return size; + } /** * Returns the minimum size of this container. @@ -717,17 +724,25 @@ */ public Dimension minimumSize() { - if(valid && minSize != null) - return new Dimension(minSize); - - LayoutManager layout = getLayout(); - if (layout != null) + Dimension size = minSize; + // Try to return cached value if possible. + if (size == null || !(minSizeSet || valid)) { - minSize = layout.minimumLayoutSize (this); - return minSize; + // Need to lock here. + synchronized (getTreeLock()) + { + LayoutManager l = layoutMgr; + if (l != null) + minSize = l.minimumLayoutSize(this); + else + minSize = super.minimumSizeImpl(); + size = minSize; } + } + if (size != null) + return new Dimension(size); else - return super.minimumSize (); + return size; } /** @@ -737,18 +752,26 @@ */ public Dimension getMaximumSize() { - if (valid && maxSize != null) - return new Dimension(maxSize); - - LayoutManager layout = getLayout(); - if (layout != null && layout instanceof LayoutManager2) + Dimension size = maxSize; + // Try to return cached value if possible. + if (size == null || !(maxSizeSet || valid)) { - LayoutManager2 lm2 = (LayoutManager2) layout; - maxSize = lm2.maximumLayoutSize(this); - return maxSize; + // Need to lock here. + synchronized (getTreeLock()) + { + LayoutManager l = layoutMgr; + if (l instanceof LayoutManager2) + maxSize = ((LayoutManager2) l).maximumLayoutSize(this); + else { + maxSize = super.maximumSizeImpl(); } + size = maxSize; + } + } + if (size != null) + return new Dimension(size); else - return super.getMaximumSize(); + return size; } /** @@ -764,9 +787,12 @@ float alignmentX = 0.0F; if (layout != null && layout instanceof LayoutManager2) { + synchronized (getTreeLock()) + { LayoutManager2 lm2 = (LayoutManager2) layout; alignmentX = lm2.getLayoutAlignmentX(this); } + } else alignmentX = super.getAlignmentX(); return alignmentX; @@ -785,9 +811,12 @@ float alignmentY = 0.0F; if (layout != null && layout instanceof LayoutManager2) { + synchronized (getTreeLock()) + { LayoutManager2 lm2 = (LayoutManager2) layout; alignmentY = lm2.getLayoutAlignmentY(this); } + } else alignmentY = super.getAlignmentY(); return alignmentY; @@ -804,14 +833,11 @@ */ public void paint(Graphics g) { - if (!isShowing()) - return; - - // Visit heavyweights if the background was cleared - // for this container. - visitChildren(g, GfxPaintVisitor.INSTANCE, !backCleared); - backCleared = false; + if (isShowing()) + { + visitChildren(g, GfxPaintVisitor.INSTANCE, true); } + } /** * Updates this container. The implementation of this method in this @@ -840,15 +866,16 @@ // that overrides isLightweight() to return false, the background is // also not cleared. So we do a check on !(peer instanceof LightweightPeer) // instead. + if (isShowing()) + { ComponentPeer p = peer; - if (p != null && ! (p instanceof LightweightPeer)) + if (! (p instanceof LightweightPeer)) { g.clearRect(0, 0, getWidth(), getHeight()); - backCleared = true; } - paint(g); } + } /** * Prints this container. The implementation of this method in this @@ -872,8 +899,8 @@ */ public void paintComponents(Graphics g) { - paint(g); - visitChildren(g, GfxPaintAllVisitor.INSTANCE, true); + if (isShowing()) + visitChildren(g, GfxPaintAllVisitor.INSTANCE, false); } /** @@ -1183,9 +1210,12 @@ */ public void addNotify() { + synchronized (getTreeLock()) + { super.addNotify(); addNotifyContainerChildren(); } + } /** * Called when this container is removed from its parent container to @@ -1196,8 +1226,14 @@ { synchronized (getTreeLock ()) { - for (int i = 0; i < ncomponents; ++i) - component[i].removeNotify(); + int ncomps = ncomponents; + Component[] comps = component; + for (int i = ncomps - 1; i >= 0; --i) + { + Component comp = comps[i]; + if (comp != null) + comp.removeNotify(); + } super.removeNotify(); } } @@ -1294,7 +1330,8 @@ * * @since 1.4 */ - public void setFocusTraversalKeys(int id, Set keystrokes) + public void setFocusTraversalKeys(int id, + Set<? extends AWTKeyStroke> keystrokes) { if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && @@ -1382,7 +1419,8 @@ if (focusTraversalKeys == null) focusTraversalKeys = new Set[4]; - keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes)); + keystrokes = + Collections.unmodifiableSet(new HashSet<AWTKeyStroke>(keystrokes)); firePropertyChange (name, focusTraversalKeys[id], keystrokes); focusTraversalKeys[id] = keystrokes; @@ -1400,7 +1438,7 @@ * * @since 1.4 */ - public Set getFocusTraversalKeys (int id) + public Set<AWTKeyStroke> getFocusTraversalKeys (int id) { if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && @@ -1641,8 +1679,17 @@ { if (orientation == null) throw new NullPointerException (); + + setComponentOrientation(orientation); + for (int i = 0; i < ncomponents; i++) + { + if (component[i] instanceof Container) + ((Container) component[i]).applyComponentOrientation(orientation); + else + component[i].setComponentOrientation(orientation); } - + } + public void addPropertyChangeListener (PropertyChangeListener listener) { // TODO: Why is this overridden? @@ -1692,6 +1739,8 @@ if (comp == this) throw new IllegalArgumentException("cannot add component to itself"); + synchronized (getTreeLock()) + { // FIXME: Implement reparenting. if ( comp.getParent() != this) throw new AssertionError("Reparenting is not implemented yet"); @@ -1712,6 +1761,7 @@ component[index] = comp; } } + } /** * Returns the Z ordering index of <code>comp</code>. If <code>comp</code> @@ -1728,10 +1778,12 @@ */ public final int getComponentZOrder(Component comp) { + synchronized (getTreeLock()) + { int index = -1; if (component != null) { - for (int i = 0; i < component.length; i++) + for (int i = 0; i < ncomponents; i++) { if (component[i] == comp) { @@ -1742,6 +1794,7 @@ } return index; } + } // Hidden helper methods. Modified: trunk/core/src/classpath/java/java/awt/Window.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Window.java 2007-01-31 21:51:44 UTC (rev 3100) +++ trunk/core/src/classpath/java/java/awt/Window.java 2007-02-03 15:05:27 UTC (rev 3101) @@ -410,8 +410,9 @@ { if (peer != null) { - WindowPeer wp = (WindowPeer) peer; - wp.toBack(); + if( alwaysOnTop ) + setAlwaysOnTop( false ); + ( (WindowPeer) peer ).toBack(); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-31 21:51:51
|
Revision: 3100 http://jnode.svn.sourceforge.net/jnode/?rev=3100&view=rev Author: lsantha Date: 2007-01-31 13:51:44 -0800 (Wed, 31 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/awt/DefaultKeyboardFocusManager.java trunk/core/src/classpath/java/java/awt/KeyboardFocusManager.java trunk/core/src/classpath/java/java/awt/TextArea.java trunk/core/src/classpath/java/java/awt/TextComponent.java trunk/core/src/classpath/java/java/awt/TextField.java trunk/core/src/classpath/java/java/awt/Toolkit.java Modified: trunk/core/src/classpath/java/java/awt/DefaultKeyboardFocusManager.java =================================================================== --- trunk/core/src/classpath/java/java/awt/DefaultKeyboardFocusManager.java 2007-01-31 20:25:09 UTC (rev 3099) +++ trunk/core/src/classpath/java/java/awt/DefaultKeyboardFocusManager.java 2007-01-31 21:51:44 UTC (rev 3100) @@ -256,6 +256,95 @@ return false; } + /** + * Handles FOCUS_GAINED events in {@link #dispatchEvent(AWTEvent)}. + * + * @param fe the focus event + */ + private boolean handleFocusGained(FocusEvent fe) + { + Component target = fe.getComponent (); + + // If old focus owner != new focus owner, notify old focus + // owner that it has lost focus. + Component oldFocusOwner = getGlobalFocusOwner(); + if (oldFocusOwner != null && oldFocusOwner != target) + { + FocusEvent lost = new FocusEvent(oldFocusOwner, + FocusEvent.FOCUS_LOST, + fe.isTemporary(), target); + oldFocusOwner.dispatchEvent(lost); + } + + setGlobalFocusOwner (target); + if (target != getGlobalFocusOwner()) + { + // Focus transfer was rejected, like when the target is not + // focusable. + dequeueKeyEvents(-1, target); + // FIXME: Restore focus somehow. + } + else + { + if (! fe.isTemporary()) + { + setGlobalPermanentFocusOwner (target); + if (target != getGlobalPermanentFocusOwner()) + { + // Focus transfer was rejected, like when the target is not + // focusable. + dequeueKeyEvents(-1, target); + // FIXME: Restore focus somehow. + } + else + { + redispatchEvent(target, fe); + } + } + } + + return true; + } + + /** + * Handles FOCUS_LOST events for {@link #dispatchEvent(AWTEvent)}. + * + * @param fe the focus event + * + * @return if the event has been handled + */ + private boolean handleFocusLost(FocusEvent fe) + { + Component currentFocus = getGlobalFocusOwner(); + if (currentFocus != fe.getOppositeComponent()) + { + setGlobalFocusOwner(null); + if (getGlobalFocusOwner() != null) + { + // TODO: Is this possible? If so, then we should try to restore + // the focus. + } + else + { + if (! fe.isTemporary()) + { + setGlobalPermanentFocusOwner(null); + if (getGlobalPermanentFocusOwner() != null) + { + // TODO: Is this possible? If so, then we should try to + // restore the focus. + } + else + { + fe.setSource(currentFocus); + redispatchEvent(currentFocus, fe); + } + } + } + } + return true; + } + private boolean enqueueKeyEvent (KeyEvent e) { Iterator i = delayRequests.iterator (); Modified: trunk/core/src/classpath/java/java/awt/KeyboardFocusManager.java =================================================================== --- trunk/core/src/classpath/java/java/awt/KeyboardFocusManager.java 2007-01-31 20:25:09 UTC (rev 3099) +++ trunk/core/src/classpath/java/java/awt/KeyboardFocusManager.java 2007-01-31 21:51:44 UTC (rev 3100) @@ -561,7 +561,9 @@ * @see #UP_CYCLE_TRAVERSAL_KEYS * @see #DOWN_CYCLE_TRAVERSAL_KEYS */ - public void setDefaultFocusTraversalKeys (int id, Set keystrokes) + public void setDefaultFocusTraversalKeys (int id, + Set<? extends AWTKeyStroke> + keystrokes) { if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && @@ -633,7 +635,7 @@ * @see #UP_CYCLE_TRAVERSAL_KEYS * @see #DOWN_CYCLE_TRAVERSAL_KEYS */ - public Set getDefaultFocusTraversalKeys (int id) + public Set<AWTKeyStroke> getDefaultFocusTraversalKeys (int id) { if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS) throw new IllegalArgumentException (); @@ -995,9 +997,9 @@ * @return A list of explicitly registered key event dispatchers. * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher) */ - protected List getKeyEventDispatchers () + protected List<KeyEventDispatcher> getKeyEventDispatchers () { - return (List) keyEventDispatchers.clone (); + return (List<KeyEventDispatcher>) keyEventDispatchers.clone (); } /** @@ -1052,9 +1054,9 @@ * @return A list of explicitly registered key event post processors. * @see KeyboardFocusManager#addKeyEventPostProcessor(java.awt.KeyEventPostProcessor) */ - protected List getKeyEventPostProcessors () + protected List<KeyEventPostProcessor> getKeyEventPostProcessors () { - return (List) keyEventPostProcessors.clone (); + return (List<KeyEventPostProcessor>) keyEventPostProcessors.clone (); } /** @@ -1436,4 +1438,48 @@ } } } + + + /** + * Maps focus requests from heavyweight to lightweight components. + */ + private static HashMap focusRequests = new HashMap(); + + /** + * Retargets focus events that come from the peer (which only know about + * heavyweight components) to go to the correct lightweight component + * if appropriate. + * + * @param ev the event to check + * + * @return the retargetted event + */ + static AWTEvent retargetFocusEvent(AWTEvent ev) + { + if (ev instanceof FocusEvent) + { + FocusEvent fe = (FocusEvent) ev; + Component target = fe.getComponent(); + if (focusRequests.containsKey(target)) + { + Component lightweight = (Component) focusRequests.get(target); + ev = new FocusEvent(lightweight, fe.id, fe.isTemporary()); + focusRequests.remove(target); } + } + return ev; + } + + /** + * Adds a lightweight focus request for a heavyweight component. + * + * @param heavyweight the heavyweight from which we will receive a focus + * event soon + * @param lightweight the lightweight that ultimately receives the request + */ + static void addLightweightFocusRequest(Component heavyweight, + Component lightweight) + { + focusRequests.put(heavyweight, lightweight); + } +} Modified: trunk/core/src/classpath/java/java/awt/TextArea.java =================================================================== --- trunk/core/src/classpath/java/java/awt/TextArea.java 2007-01-31 20:25:09 UTC (rev 3099) +++ trunk/core/src/classpath/java/java/awt/TextArea.java 2007-01-31 21:51:44 UTC (rev 3100) @@ -125,9 +125,11 @@ * the specified text. Conceptually the <code>TextArea</code> has 0 * rows and 0 columns but its initial bounds are defined by its peer * or by the container in which it is packed. Both horizontal and - * veritcal scrollbars will be displayed. + * veritcal scrollbars will be displayed. The TextArea initially contains + * the specified text. If text specified as <code>null<code>, it will + * be set to "". * - * @param text The text to display in this text area. + * @param text The text to display in this text area (<code>null</code> permitted). * * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true */ @@ -156,9 +158,10 @@ * Initialize a new instance of <code>TextArea</code> that can * display the specified number of rows and columns of text, without * the need to scroll. The TextArea initially contains the - * specified text. + * specified text. If text specified as <code>null<code>, it will + * be set to "". * - * @param text The text to display in this text area. + * @param text The text to display in this text area (<code>null</code> permitted). * @param rows The number of rows in this text area. * @param columns The number of columns in this text area. * @@ -174,9 +177,10 @@ * contains the specified text. The TextArea can display the * specified number of rows and columns of text, without the need to * scroll. This constructor allows specification of the scroll bar - * display policy. + * display policy. The TextArea initially contains the specified text. + * If text specified as <code>null<code>, it will be set to "". * - * @param text The text to display in this text area. + * @param text The text to display in this text area (<code>null</code> permitted). * @param rows The number of rows in this text area. * @param columns The number of columns in this text area. * @param scrollbarVisibility The scroll bar display policy. One of @@ -192,17 +196,19 @@ if (GraphicsEnvironment.isHeadless ()) throw new HeadlessException (); - if (rows < 0 || columns < 0) - throw new IllegalArgumentException ("Bad row or column value"); + if (rows < 0) + this.rows = 0; + else + this.rows = rows; - if (scrollbarVisibility != SCROLLBARS_BOTH - && scrollbarVisibility != SCROLLBARS_VERTICAL_ONLY - && scrollbarVisibility != SCROLLBARS_HORIZONTAL_ONLY - && scrollbarVisibility != SCROLLBARS_NONE) - throw new IllegalArgumentException ("Bad scrollbar visibility value"); + if (columns < 0) + this.columns = 0; + else + this.columns = columns; - this.rows = rows; - this.columns = columns; + if (scrollbarVisibility < 0 || scrollbarVisibility > 4) + this.scrollbarVisibility = SCROLLBARS_BOTH; + else this.scrollbarVisibility = scrollbarVisibility; // TextAreas need to receive tab key events so we override the @@ -278,11 +284,7 @@ } /** - * Retrieve the minimum size for this text area, considering the - * text area's current row and column values. A text area's minimum - * size depends on the number of rows and columns of text it would - * prefer to display, and on the size of the font in which the text - * would be displayed. + * Retrieve the minimum size for this text area. * * @return The minimum size for this text field. */ @@ -292,11 +294,8 @@ } /** - * Retrieve the minimum size that this text area would have if its - * row and column values were equal to those specified. A text - * area's minimum size depends on the number of rows and columns of - * text it would prefer to display, and on the size of the font in - * which the text would be displayed. + * Retrieve the minimum size for this text area. If the minimum + * size has been set, then rows and columns are used in the calculation. * * @param rows The number of rows to use in the minimum size * calculation. @@ -311,11 +310,7 @@ } /** - * Retrieve the minimum size for this text area, considering the - * text area's current row and column values. A text area's minimum - * size depends on the number of rows and columns of text it would - * prefer to display, and on the size of the font in which the text - * would be displayed. + * Retrieve the minimum size for this text area. * * @return The minimum size for this text area. * @@ -328,11 +323,8 @@ } /** - * Retrieve the minimum size that this text area would have if its - * row and column values were equal to those specified. A text - * area's minimum size depends on the number of rows and columns of - * text it would prefer to display, and on the size of the font in - * which the text would be displayed. + * Retrieve the minimum size for this text area. If the minimum + * size has been set, then rows and columns are used in the calculation. * * @param rows The number of rows to use in the minimum size * calculation. @@ -346,21 +338,18 @@ */ public Dimension minimumSize (int rows, int columns) { + if (isMinimumSizeSet()) + return new Dimension(minSize); + TextAreaPeer peer = (TextAreaPeer) getPeer (); - - // Sun returns Dimension (0,0) in this case. if (peer == null) - return new Dimension (0, 0); + return new Dimension (getWidth(), getHeight()); return peer.getMinimumSize (rows, columns); } /** - * Retrieve the preferred size for this text area, considering the - * text area's current row and column values. A text area's preferred - * size depends on the number of rows and columns of text it would - * prefer to display, and on the size of the font in which the text - * would be displayed. + * Retrieve the preferred size for this text area. * * @return The preferred size for this text field. */ @@ -370,11 +359,8 @@ } /** - * Retrieve the preferred size that this text area would have if its - * row and column values were equal to those specified. A text - * area's preferred size depends on the number of rows and columns - * of text it would prefer to display, and on the size of the font - * in which the text would be displayed. + * Retrieve the preferred size for this text area. If the preferred + * size has been set, then rows and columns are used in the calculation. * * @param rows The number of rows to use in the preferred size * calculation. @@ -389,11 +375,7 @@ } /** - * Retrieve the preferred size for this text area, considering the - * text area's current row and column values. A text area's preferred - * size depends on the number of rows and columns of text it would - * prefer to display, and on the size of the font in which the text - * would be displayed. + * Retrieve the preferred size for this text area. * * @return The preferred size for this text field. * @@ -406,11 +388,8 @@ } /** - * Retrieve the preferred size that this text area would have if its - * row and column values were equal to those specified. A text - * area's preferred size depends on the number of rows and columns - * of text it would prefer to display, and on the size of the font - * in which the text would be displayed. + * Retrieve the preferred size for this text area. If the preferred + * size has been set, then rows and columns are used in the calculation. * * @param rows The number of rows to use in the preferred size * calculation. @@ -424,11 +403,12 @@ */ public Dimension preferredSize (int rows, int columns) { + if (isPreferredSizeSet()) + return new Dimension(prefSize); + TextAreaPeer peer = (TextAreaPeer) getPeer (); - - // Sun returns Dimension (0,0) in this case. if (peer == null) - return new Dimension (0, 0); + return new Dimension (getWidth(), getHeight()); return peer.getPreferredSize (rows, columns); } @@ -478,6 +458,8 @@ if (peer != null) peer.insert (str, peer.getText().length ()); + else + setText(getText() + str); } /** @@ -504,11 +486,20 @@ */ public void insertText (String str, int pos) { + String tmp1 = null; + String tmp2 = null; + TextAreaPeer peer = (TextAreaPeer) getPeer (); if (peer != null) peer.insert (str, pos); + else + { + tmp1 = getText().substring(0, pos); + tmp2 = getText().substring(pos, getText().length()); + setText(tmp1 + str + tmp2); } + } /** * Replace a range of characters with the specified text. The @@ -544,11 +535,20 @@ */ public void replaceText (String str, int start, int end) { - TextAreaPeer peer = (TextAreaPeer) getPeer (); + String tmp1 = null; + String tmp2 = null; + TextAreaPeer peer = (TextAreaPeer) getPeer(); + if (peer != null) - peer.replaceRange (str, start, end); + peer.replaceRange(str, start, end); + else + { + tmp1 = getText().substring(0, start); + tmp2 = getText().substring(end, getText().length()); + setText(tmp1 + str + tmp2); } + } /** * Retrieve a debugging string for this text area. Modified: trunk/core/src/classpath/java/java/awt/TextComponent.java =================================================================== --- trunk/core/src/classpath/java/java/awt/TextComponent.java 2007-01-31 20:25:09 UTC (rev 3099) +++ trunk/core/src/classpath/java/java/awt/TextComponent.java 2007-01-31 21:51:44 UTC (rev 3100) @@ -1,5 +1,5 @@ /* TextComponent.java -- Widgets for entering text - Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1999, 2002, 2003, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -63,45 +63,36 @@ implements Serializable, Accessible { -/* - * Static Variables - */ + private static final long serialVersionUID = -2214773872412987419L; -// Constant for serialization -private static final long serialVersionUID = -2214773872412987419L; - -/* - * Instance Variables - */ - -/** + /** * @serial Indicates whether or not this component is editable. * This is package-private to avoid an accessor method. */ -boolean editable; + boolean editable; -/** + /** * @serial The starting position of the selected text region. * This is package-private to avoid an accessor method. */ -int selectionStart; + int selectionStart; -/** + /** * @serial The ending position of the selected text region. * This is package-private to avoid an accessor method. */ -int selectionEnd; + int selectionEnd; -/** + /** * @serial The text in the component * This is package-private to avoid an accessor method. */ -String text; + String text; -/** + /** * A list of listeners that will receive events from this object. */ -protected transient TextListener textListener; + protected transient TextListener textListener; protected class AccessibleAWTTextComponent extends AccessibleAWTComponent @@ -318,146 +309,121 @@ } -/*************************************************************************/ -/* - * Constructors - */ - -TextComponent(String text) -{ + TextComponent(String text) + { + if (text == null) + this.text = ""; + else this.text = text; + this.editable = true; -} + } -/*************************************************************************/ -/* - * Instance Methods - */ - -/** + /** * Returns the text in this component * * @return The text in this component. */ -public synchronized String -getText() -{ - TextComponentPeer tcp = (TextComponentPeer)getPeer(); + public synchronized String getText() + { + TextComponentPeer tcp = (TextComponentPeer) getPeer(); if (tcp != null) text = tcp.getText(); return(text); -} + } -/*************************************************************************/ - -/** + /** * Sets the text in this component to the specified string. * * @param text The new text for this component. */ -public synchronized void -setText(String text) -{ + public synchronized void setText(String text) + { if (text == null) text = ""; this.text = text; - TextComponentPeer tcp = (TextComponentPeer)getPeer(); + TextComponentPeer tcp = (TextComponentPeer) getPeer(); if (tcp != null) tcp.setText(text); setCaretPosition(0); -} + } -/*************************************************************************/ - -/** + /** * Returns a string that contains the text that is currently selected. * * @return The currently selected text region. */ -public synchronized String -getSelectedText() -{ + public synchronized String getSelectedText() + { String alltext = getText(); int start = getSelectionStart(); int end = getSelectionEnd(); return(alltext.substring(start, end)); -} + } -/*************************************************************************/ - -/** + /** * Returns the starting position of the selected text region. * If the text is not selected then caret position is returned. * * @return The starting position of the selected text region. */ -public synchronized int -getSelectionStart() -{ - TextComponentPeer tcp = (TextComponentPeer)getPeer(); + public synchronized int getSelectionStart() + { + TextComponentPeer tcp = (TextComponentPeer) getPeer(); if (tcp != null) selectionStart = tcp.getSelectionStart(); return(selectionStart); -} + } -/*************************************************************************/ - -/** + /** * Sets the starting position of the selected region to the * specified value. If the specified value is out of range, then it * will be silently changed to the nearest legal value. * * @param selectionStart The new start position for selected text. */ -public synchronized void -setSelectionStart(int selectionStart) -{ - select(selectionStart, getSelectionEnd()); -} + public synchronized void setSelectionStart(int selectionStart) + { + select(selectionStart, + (getSelectionEnd() < selectionStart) + ? selectionStart : getSelectionEnd()); + } -/*************************************************************************/ - -/** + /** * Returns the ending position of the selected text region. * If the text is not selected, then caret position is returned * * @return The ending position of the selected text region. */ -public synchronized int -getSelectionEnd() -{ - TextComponentPeer tcp = (TextComponentPeer)getPeer(); + public synchronized int getSelectionEnd() + { + TextComponentPeer tcp = (TextComponentPeer) getPeer(); if (tcp != null) selectionEnd = tcp.getSelectionEnd(); return(selectionEnd); -} + } -/*************************************************************************/ - -/** + /** * Sets the ending position of the selected region to the * specified value. If the specified value is out of range, then it * will be silently changed to the nearest legal value. * * @param selectionEnd The new start position for selected text. */ -public synchronized void -setSelectionEnd(int selectionEnd) -{ + public synchronized void setSelectionEnd(int selectionEnd) + { select(getSelectionStart(), selectionEnd); -} + } -/*************************************************************************/ - -/** + /** * This method sets the selected text range to the text between the * specified start and end positions. Illegal values for these * positions are silently fixed. @@ -465,9 +431,8 @@ * @param selectionStart The new start position for the selected text. * @param selectionEnd The new end position for the selected text. */ -public synchronized void -select(int selectionStart, int selectionEnd) -{ + public synchronized void select(int selectionStart, int selectionEnd) + { if (selectionStart < 0) selectionStart = 0; @@ -483,42 +448,34 @@ this.selectionStart = selectionStart; this.selectionEnd = selectionEnd; - TextComponentPeer tcp = (TextComponentPeer)getPeer(); + TextComponentPeer tcp = (TextComponentPeer) getPeer(); if (tcp != null) tcp.select(selectionStart, selectionEnd); -} + } -/*************************************************************************/ - -/** + /** * Selects all of the text in the component. */ -public synchronized void -selectAll() -{ + public synchronized void selectAll() + { select(0, getText().length()); -} + } -/*************************************************************************/ - -/** + /** * Returns the current caret position in the text. * * @return The caret position in the text. */ -public synchronized int -getCaretPosition() -{ - TextComponentPeer tcp = (TextComponentPeer)getPeer(); + public synchronized int getCaretPosition() + { + TextComponentPeer tcp = (TextComponentPeer) getPeer(); if (tcp != null) return(tcp.getCaretPosition()); else return(0); -} + } -/*************************************************************************/ - -/** + /** * Sets the caret position to the specified value. * * @param caretPosition The new caret position. @@ -528,111 +485,90 @@ * * @since 1.1 */ -public synchronized void -setCaretPosition(int caretPosition) -{ + public synchronized void setCaretPosition(int caretPosition) + { if (caretPosition < 0) - throw new IllegalArgumentException (); + throw new IllegalArgumentException(); - TextComponentPeer tcp = (TextComponentPeer)getPeer(); + TextComponentPeer tcp = (TextComponentPeer) getPeer(); if (tcp != null) tcp.setCaretPosition(caretPosition); -} + } -/*************************************************************************/ - -/** + /** * Tests whether or not this component's text can be edited. * * @return <code>true</code> if the text can be edited, <code>false</code> * otherwise. */ -public boolean -isEditable() -{ + public boolean isEditable() + { return(editable); -} + } -/*************************************************************************/ - -/** + /** * Sets whether or not this component's text can be edited. * * @param editable <code>true</code> to enable editing of the text, * <code>false</code> to disable it. */ -public synchronized void -setEditable(boolean editable) -{ + public synchronized void setEditable(boolean editable) + { this.editable = editable; - TextComponentPeer tcp = (TextComponentPeer)getPeer(); + TextComponentPeer tcp = (TextComponentPeer) getPeer(); if (tcp != null) tcp.setEditable(editable); -} + } -/*************************************************************************/ - -/** + /** * Notifies the component that it should destroy its native peer. */ -public void -removeNotify() -{ + public void removeNotify() + { super.removeNotify(); -} + } -/*************************************************************************/ - -/** + /** * Adds a new listener to the list of text listeners for this * component. * * @param listener The listener to be added. */ -public synchronized void -addTextListener(TextListener listener) -{ + public synchronized void addTextListener(TextListener listener) + { textListener = AWTEventMulticaster.add(textListener, listener); enableEvents(AWTEvent.TEXT_EVENT_MASK); -} + } -/*************************************************************************/ - -/** + /** * Removes the specified listener from the list of listeners * for this component. * * @param listener The listener to remove. */ -public synchronized void -removeTextListener(TextListener listener) -{ + public synchronized void removeTextListener(TextListener listener) + { textListener = AWTEventMulticaster.remove(textListener, listener); -} + } -/*************************************************************************/ - -/** + /** * Processes the specified event for this component. Text events are * processed by calling the <code>processTextEvent()</code> method. * All other events are passed to the superclass method. * * @param event The event to process. */ -protected void -processEvent(AWTEvent event) -{ + protected void processEvent(AWTEvent event) + { if (event instanceof TextEvent) processTextEvent((TextEvent)event); else super.processEvent(event); -} + } -/*************************************************************************/ - -/** + /** * Processes the specified text event by dispatching it to any listeners * that are registered. Note that this method will only be called * if text event's are enabled. This will be true if there are any @@ -641,16 +577,14 @@ * * @param event The text event to process. */ -protected void -processTextEvent(TextEvent event) -{ + protected void processTextEvent(TextEvent event) + { if (textListener != null) textListener.textValueChanged(event); -} + } -void -dispatchEventImpl(AWTEvent e) -{ + void dispatchEventImpl(AWTEvent e) + { if (e.id <= TextEvent.TEXT_LAST && e.id >= TextEvent.TEXT_FIRST && (textListener != null @@ -658,20 +592,17 @@ processEvent(e); else super.dispatchEventImpl(e); -} + } -/*************************************************************************/ - -/** + /** * Returns a debugging string. * * @return A debugging string. */ -protected String -paramString() -{ + protected String paramString() + { return(getClass().getName() + "(text=" + getText() + ")"); -} + } /** * Returns an array of all the objects currently registered as FooListeners @@ -681,20 +612,20 @@ * @exception ClassCastException If listenerType doesn't specify a class or * interface that implements java.util.EventListener. */ - public EventListener[] getListeners (Class listenerType) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { if (listenerType == TextListener.class) - return AWTEventMulticaster.getListeners (textListener, listenerType); + return AWTEventMulticaster.getListeners(textListener, listenerType); - return super.getListeners (listenerType); + return super.getListeners(listenerType); } /** * Returns all text listeners registered to this object. */ - public TextListener[] getTextListeners () + public TextListener[] getTextListeners() { - return (TextListener[]) getListeners (TextListener.class); + return (TextListener[]) getListeners(TextListener.class); } /** @@ -712,30 +643,35 @@ } - /*******************************/ // Provide AccessibleAWTTextComponent access to several peer functions that // aren't publicly exposed. This is package-private to avoid an accessor // method. - synchronized int - getIndexAtPoint(Point p) + synchronized int getIndexAtPoint(Point p) { - TextComponentPeer tcp = (TextComponentPeer)getPeer(); + TextComponentPeer tcp = (TextComponentPeer) getPeer(); if (tcp != null) return tcp.getIndexAtPoint(p.x, p.y); return -1; } - synchronized Rectangle - getCharacterBounds(int i) + synchronized Rectangle getCharacterBounds(int i) { - TextComponentPeer tcp = (TextComponentPeer)getPeer(); + TextComponentPeer tcp = (TextComponentPeer) getPeer(); if (tcp != null) return tcp.getCharacterBounds(i); return null; } - + /** + * All old mouse events for this component should + * be ignored. + * + * @return true to ignore all old mouse events. + */ + static boolean ignoreOldMouseEvents() + { + return true; + } - } // class TextComponent Modified: trunk/core/src/classpath/java/java/awt/TextField.java =================================================================== --- trunk/core/src/classpath/java/java/awt/TextField.java 2007-01-31 20:25:09 UTC (rev 3099) +++ trunk/core/src/classpath/java/java/awt/TextField.java 2007-01-31 21:51:44 UTC (rev 3100) @@ -1,5 +1,5 @@ /* TextField.java -- A one line text entry field - Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 1999, 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -55,53 +55,40 @@ public class TextField extends TextComponent { -/* - * Static Variables + /** + * The number used to generate the name returned by getName. */ + private static transient long next_textfield_number; -// Serialization constant -private static final long serialVersionUID = -2966288784432217853L; -/*************************************************************************/ + private static final long serialVersionUID = -2966288784432217853L; -/* - * Instance Variables - */ -/** + /** * @serial The number of columns in the text entry field. */ -private int columns; + private int columns; -/** + /** * @serial The character that is echoed when doing protected input */ -private char echoChar; + private char echoChar; -// List of registered ActionListener's for this object. -private ActionListener action_listeners; + // List of registered ActionListener's for this object. + private ActionListener action_listeners; -/*************************************************************************/ - -/* - * Constructors - */ - -/** + /** * Initializes a new instance of <code>TextField</code> that is empty * and has one column. * * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true, */ -public -TextField() -{ - this("", 1); -} + public TextField() + { + this("", 0); + } -/*************************************************************************/ - -/** + /** * Initializes a new instance of <code>TextField</code> containing * the specified text. The number of columns will be equal to the * length of the text string. @@ -110,15 +97,12 @@ * * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true, */ -public -TextField(String text) -{ - this(text, text.length()); -} + public TextField(String text) + { + this(text, (text == null) ? 0 : text.length()); + } -/*************************************************************************/ - -/** + /** * Initializes a new instance of <code>TextField</code> that is empty * and has the specified number of columns. * @@ -126,15 +110,12 @@ * * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true, */ -public -TextField(int columns) -{ + public TextField(int columns) + { this("", columns); -} + } -/*************************************************************************/ - -/** + /** * Initializes a new instance of <code>TextField</code> with the * specified text and number of columns. * @@ -143,84 +124,69 @@ * * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true, */ -public -TextField(String text, int columns) -{ + public TextField(String text, int columns) + { super(text); + + if (columns < 0) + this.columns = 0; + else this.columns = columns; if (GraphicsEnvironment.isHeadless()) throw new HeadlessException (); -} + } -/*************************************************************************/ - -/* - * Instance Methods - */ - -/** + /** * Returns the number of columns in the field. * * @return The number of columns in the field. */ -public int -getColumns() -{ + public int getColumns() + { return(columns); -} + } -/*************************************************************************/ - -/** + /** * Sets the number of columns in this field to the specified value. * * @param columns The new number of columns in the field. * * @exception IllegalArgumentException If columns is less than zero. */ -public synchronized void -setColumns(int columns) -{ + public synchronized void setColumns(int columns) + { if (columns < 0) throw new IllegalArgumentException("Value is less than zero: " + columns); this.columns = columns; // FIXME: How to we communicate this to our peer? -} + } -/*************************************************************************/ - -/** + /** * Returns the character that is echoed to the screen when a text * field is protected (such as when a password is being entered). * * @return The echo character for this text field. */ -public char -getEchoChar() -{ + public char getEchoChar() + { return(echoChar); -} + } -/*************************************************************************/ - -/** + /** * Sets the character that is echoed when protected input such as * a password is displayed. * * @param echoChar The new echo character. */ -public void -setEchoChar(char echoChar) -{ - setEchoCharacter (echoChar); -} + public void setEchoChar(char echoChar) + { + setEchoCharacter(echoChar); + } -/*************************************************************************/ - -/** + /** * Sets the character that is echoed when protected input such as * a password is displayed. * @@ -229,64 +195,52 @@ * @deprecated This method is deprecated in favor of * <code>setEchoChar()</code> */ -public void -setEchoCharacter(char echoChar) -{ + public void setEchoCharacter(char echoChar) + { this.echoChar = echoChar; TextFieldPeer peer = (TextFieldPeer) getPeer (); if (peer != null) peer.setEchoChar (echoChar); -} + } -/*************************************************************************/ - -/** + /** * Tests whether or not this text field has an echo character set * so that characters the user type are not echoed to the screen. * * @return <code>true</code> if an echo character is set, * <code>false</code> otherwise. */ -public boolean -echoCharIsSet() -{ + public boolean echoCharIsSet() + { if (echoChar == '\u0000') return(false); else return(true); -} + } -/*************************************************************************/ - -/** + /** * Returns the minimum size for this text field. * * @return The minimum size for this text field. */ -public Dimension -getMinimumSize() -{ + public Dimension getMinimumSize() + { return getMinimumSize (getColumns ()); -} + } -/*************************************************************************/ - -/** + /** * Returns the minimum size of a text field with the specified number * of columns. * * @param columns The number of columns to get the minimum size for. */ -public Dimension -getMinimumSize(int columns) -{ - return minimumSize (columns); -} + public Dimension getMinimumSize(int columns) + { + return minimumSize(columns); + } -/*************************************************************************/ - -/** + /** * Returns the minimum size for this text field. * * @return The minimum size for this text field. @@ -294,15 +248,12 @@ * @deprecated This method is deprecated in favor of * <code>getMinimumSize()</code>. */ -public Dimension -minimumSize() -{ - return minimumSize (getColumns ()); -} + public Dimension minimumSize() + { + return minimumSize(getColumns ()); + } -/*************************************************************************/ - -/** + /** * Returns the minimum size of a text field with the specified number * of columns. * @@ -311,46 +262,40 @@ * @deprecated This method is deprecated in favor of * <code>getMinimumSize(int)</code>. */ -public Dimension -minimumSize(int columns) -{ + public Dimension minimumSize(int columns) + { + if (isMinimumSizeSet()) + return new Dimension(minSize); + TextFieldPeer peer = (TextFieldPeer) getPeer (); if (peer == null) - return null; // FIXME: What do we do if there is no peer? + return new Dimension(getWidth(), getHeight()); return peer.getMinimumSize (columns); -} + } -/*************************************************************************/ - -/** + /** * Returns the preferred size for this text field. * * @return The preferred size for this text field. */ -public Dimension -getPreferredSize() -{ - return getPreferredSize (getColumns ()); -} + public Dimension getPreferredSize() + { + return getPreferredSize(getColumns ()); + } -/*************************************************************************/ - -/** + /** * Returns the preferred size of a text field with the specified number * of columns. * * @param columns The number of columns to get the preferred size for. */ -public Dimension -getPreferredSize(int columns) -{ - return preferredSize (columns); -} + public Dimension getPreferredSize(int columns) + { + return preferredSize(columns); + } -/*************************************************************************/ - -/** + /** * Returns the preferred size for this text field. * * @return The preferred size for this text field. @@ -358,15 +303,12 @@ * @deprecated This method is deprecated in favor of * <code>getPreferredSize()</code>. */ -public Dimension -preferredSize() -{ - return preferredSize (getColumns ()); -} + public Dimension preferredSize() + { + return preferredSize(getColumns ()); + } -/*************************************************************************/ - -/** + /** * Returns the preferred size of a text field with the specified number * of columns. * @@ -375,63 +317,55 @@ * @deprecated This method is deprecated in favor of * <code>getPreferredSize(int)</code>. */ -public Dimension -preferredSize(int columns) -{ + public Dimension preferredSize(int columns) + { + if (isPreferredSizeSet()) + return new Dimension(prefSize); + TextFieldPeer peer = (TextFieldPeer) getPeer (); if (peer == null) - return new Dimension (0, 0); + return new Dimension (getWidth(), getHeight()); return peer.getPreferredSize (columns); -} + } -/*************************************************************************/ - -/** + /** * Notifies this object that it should create its native peer. */ -public void -addNotify() -{ + public void addNotify() + { if (getPeer() != null) return; setPeer((ComponentPeer)getToolkit().createTextField(this)); -} + super.addNotify(); + } -/*************************************************************************/ - -/** + /** * Addes a new listener to the list of action listeners for this * object. * * @param listener The listener to add to the list. */ -public synchronized void -addActionListener(ActionListener listener) -{ + public synchronized void addActionListener(ActionListener listener) + { action_listeners = AWTEventMulticaster.add(action_listeners, listener); enableEvents(AWTEvent.ACTION_EVENT_MASK); -} + } -/*************************************************************************/ - -/** + /** * Removes the specified listener from the list of action listeners * for this object. * * @param listener The listener to remove from the list. */ -public synchronized void -removeActionListener(ActionListener listener) -{ + public synchronized void removeActionListener(ActionListener listener) + { action_listeners = AWTEventMulticaster.remove(action_listeners, listener); -} + } -/*************************************************************************/ - -/** + /** * Processes the specified event. If the event is an instance of * <code>ActionEvent</code> then <code>processActionEvent()</code> is * called to process it, otherwise the event is sent to the @@ -439,18 +373,15 @@ * * @param event The event to process. */ -protected void -processEvent(AWTEvent event) -{ + protected void processEvent(AWTEvent event) + { if (event instanceof ActionEvent) processActionEvent((ActionEvent)event); else super.processEvent(event); -} + } -/*************************************************************************/ - -/** + /** * Processes an action event by calling any registered listeners. * Note to subclasses: This method is not called unless action events * are enabled on this object. This will be true if any listeners @@ -459,16 +390,14 @@ * * @param event The event to process. */ -protected void -processActionEvent(ActionEvent event) -{ + protected void processActionEvent(ActionEvent event) + { if (action_listeners != null) action_listeners.actionPerformed(event); -} + } -void -dispatchEventImpl(AWTEvent e) -{ + void dispatchEventImpl(AWTEvent e) + { if (e.id <= ActionEvent.ACTION_LAST && e.id >= ActionEvent.ACTION_FIRST && (action_listeners != null @@ -476,21 +405,18 @@ processEvent(e); else super.dispatchEventImpl(e); -} + } -/*************************************************************************/ - -/** + /** * Returns a debug string for this object. * * @return A debug string for this object. */ -protected String -paramString() -{ + protected String paramString() + { return(getClass().getName() + "(columns=" + getColumns() + ",echoChar=" + getEchoChar()); -} + } /** * Returns an array of all the objects currently registered as FooListeners @@ -502,7 +428,7 @@ * * @since 1.3 */ - public EventListener[] getListeners (Class listenerType) + public <T extends EventListener> T[] getListeners (Class<T> listenerType) { if (listenerType == ActionListener.class) return AWTEventMulticaster.getListeners (action_listeners, listenerType); @@ -521,6 +447,21 @@ return (ActionListener[]) getListeners (ActionListener.class); } + /** + * Generate a unique name for this <code>TextField</code>. + * + * @return A unique name for this <code>TextField</code>. + */ + String generateName() + { + return "textfield" + getUniqueLong(); + } + + private static synchronized long getUniqueLong() + { + return next_textfield_number++; + } + protected class AccessibleAWTTextField extends AccessibleAWTTextComponent { private static final long serialVersionUID = 6219164359235943158L; @@ -540,4 +481,4 @@ return new AccessibleAWTTextField(); } -} // class TextField +} Modified: trunk/core/src/classpath/java/java/awt/Toolkit.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Toolkit.java 2007-01-31 20:25:09 UTC (rev 3099) +++ trunk/core/src/classpath/java/java/awt/Toolkit.java 2007-01-31 21:51:44 UTC (rev 3100) @@ -1,5 +1,5 @@ /* Toolkit.java -- AWT Toolkit superclass - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,7 +39,10 @@ package java.awt; +import gnu.classpath.SystemProperties; +import gnu.java.awt.AWTUtilities; import gnu.java.awt.peer.GLightweightPeer; +import gnu.java.awt.peer.headless.HeadlessToolkit; import java.awt.datatransfer.Clipboard; import java.awt.dnd.DragGestureEvent; @@ -50,6 +53,7 @@ import java.awt.event.AWTEventListener; import java.awt.event.AWTEventListenerProxy; import java.awt.event.KeyEvent; +import java.awt.font.TextAttribute; import java.awt.im.InputMethodHighlight; import java.awt.image.ColorModel; import java.awt.image.ImageObserver; @@ -69,6 +73,7 @@ import java.awt.peer.MenuBarPeer; import java.awt.peer.MenuItemPeer; import java.awt.peer.MenuPeer; +import java.awt.peer.MouseInfoPeer; import java.awt.peer.PanelPeer; import java.awt.peer.PopupMenuPeer; import java.awt.peer.ScrollPanePeer; @@ -76,13 +81,18 @@ import java.awt.peer.TextAreaPeer; import java.awt.peer.TextFieldPeer; import java.awt.peer.WindowPeer; -import java.awt.peer.MouseInfoPeer; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; +import java.io.File; +import java.io.FileInputStream; import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; +import java.util.Hashtable; import java.util.Map; import java.util.Properties; +import java.util.StringTokenizer; /** * The AWT system uses a set of native peer objects to implement its @@ -113,7 +123,8 @@ /** The toolkit properties. */ private static Properties props = new Properties(); - protected final Map desktopProperties = new Properties(); + protected final Map<String,Object> desktopProperties = + new Hashtable<String,Object>(); protected final PropertyChangeSupport desktopPropsSupport = new PropertyChangeSupport(this); @@ -541,11 +552,12 @@ * * @throws AWTError If the toolkit cannot be loaded. */ - public static Toolkit getDefaultToolkit() + public static synchronized Toolkit getDefaultToolkit() { if (toolkit != null) return toolkit; - String toolkit_name = System.getProperty("awt.toolkit", + + String toolkit_name = SystemProperties.getProperty("awt.toolkit", default_toolkit_name); try { @@ -559,6 +571,8 @@ throw new AWTError(toolkit_name + " is not a subclass of " + "java.awt.Toolkit"); toolkit = (Toolkit) obj; + + initAccessibility(); return toolkit; } catch (ThreadDeath death) @@ -567,9 +581,19 @@ } catch (Throwable t) { - AWTError e = new AWTError("Cannot load AWT toolkit: " + toolkit_name); + // Check for the headless property. + if (GraphicsEnvironment.isHeadless()) + { + toolkit = new HeadlessToolkit(); + return toolkit; + } + else + { + AWTError e = new AWTError("Cannot load AWT toolkit: " + + toolkit_name); throw (AWTError) e.initCause(t); - } + } + } } // @classpath-bugfix @@ -711,6 +735,14 @@ public PrintJob getPrintJob(Frame frame, String title, JobAttributes jobAttr, PageAttributes pageAttr) { + // FIXME: it is possible this check may be removed + // if this method, when written, always delegates to + // getPrintJob(Frame, String, Properties). + SecurityManager sm; + sm = System.getSecurityManager(); + if (sm != null) + sm.checkPrintJobAccess(); + return null; } @@ -775,12 +807,11 @@ */ public boolean getLockingKeyState(int keyCode) { - if (keyCode != KeyEvent.VK_CAPS_LOCK - && keyCode != KeyEvent.VK_NUM_LOCK - && keyCode != KeyEvent.VK_SCROLL_LOCK) - throw new IllegalArgumentException(); + if (AWTUtilities.isValidKey(keyCode)) + throw new UnsupportedOperationException + ("cannot get locking state of key code " + keyCode); - throw new UnsupportedOperationException(); + throw new IllegalArgumentException("invalid key code " + keyCode); } /** @@ -959,8 +990,8 @@ /** * @since 1.3 */ - public DragGestureRecognizer - createDragGestureRecognizer(Class recognizer, DragSource ds, + public <T extends DragGestureRecognizer> T + createDragGestureRecognizer(Class<T> recognizer, DragSource ds, Component comp, int actions, DragGestureListener l) { @@ -1247,5 +1278,140 @@ /** * @since 1.3 */ - public abstract Map mapInputMethodHighlight(InputMethodHighlight highlight); + public abstract Map<TextAttribute,?> + mapInputMethodHighlight(InputMethodHighlight highlight); + + /** + * Initializes the accessibility framework. In particular, this loads the + * properties javax.accessibility.screen_magnifier_present and + * javax.accessibility.screen_reader_present and loads + * the classes specified in javax.accessibility.assistive_technologies. + */ + private static void initAccessibility() + { + AccessController.doPrivileged + (new PrivilegedAction() + { + public Object run() + { + Properties props = new Properties(); + String sep = File.separator; + + // Try the user configuration. + try + { + File propsFile = new File(System.getProperty("user.home") + sep + + ".accessibility.properties"); + FileInputStream in = new FileInputStream(propsFile); + props.load(in); + in.close(); + } + catch (Exception ex) + { + // User configuration not present, ignore. + } + + // Try the system configuration if there was no user configuration. + if (props.size() == 0) + { + try + { + File propsFile = + new File(System.getProperty("gnu.classpath.home.url") + + sep + "accessibility.properties"); + FileInputStream in = new FileInputStream(propsFile); + props.load(in); + in.close(); + } + catch (Exception ex) + { + // System configuration not present, ignore. + } + } + + // Fetch the screen_magnifier_present property. Check systen properties + // first, then fallback to the configuration file. + String magPresent = SystemProperties.getProperty + ("javax.accessibility.screen_magnifier_present"); + if (magPresent == null) + { + magPresent = props.getProperty("screen_magnifier_present"); + if (magPresent != null) + { + SystemProperties.setProperty + ("javax.accessibility.screen_magnifier_present", magPresent); + } + } + + // Fetch the screen_reader_present property. Check systen properties + // first, then fallback to the configuration file. + String readerPresent = SystemProperties.getProperty + ("javax.accessibility.screen_reader_present"); + if (readerPresent == null) + { + readerPresent = props.getProperty("screen_reader_present"); + if (readerPresent != null) + { + SystemProperties.setProperty + ("javax.accessibility.screen_reader_present", readerPresent); + } + } + + // Fetch the list of classes to be loaded. + String classes = SystemProperties.getProperty + ("javax.accessibility.assistive_technologies"); + if (classes == null) + { + classes = props.getProperty("assistive_technologies"); + if (classes != null) + { + SystemProperties.setProperty + ("javax.accessibility.assistive_technologies", classes); + } + } + + // Try to load the assisitive_technologies classes. + if (classes != null) + { + ClassLoader cl = ClassLoader.getSystemClassLoader(); + StringTokenizer tokenizer = new StringTokenizer(classes, ","); + while (tokenizer.hasMoreTokens()) + { + String className = tokenizer.nextToken(); + try + { + Class atClass = cl.loadClass(className); + atClass.newInstance(); + } + catch (ClassNotFoundException ex) + { + AWTError err = new AWTError("Assistive Technology class not" + + " found: " + className); + err.initCause(ex); + throw err; + } + catch (InstantiationException ex) + { + AWTError err = + new AWTError("Assistive Technology class cannot be " + + "instantiated: " + className); + err.initCause(ex); + throw err; + } + catch (IllegalAccessException ex) + { + AWTError err = + new AWTError("Assistive Technology class cannot be " + + "accessed: " + className); + err.initCause(err); + throw err; + } + } + } + return null; + } + }); + + } + } // class Toolkit This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-31 20:25:36
|
Revision: 3099 http://jnode.svn.sourceforge.net/jnode/?rev=3099&view=rev Author: lsantha Date: 2007-01-31 12:25:09 -0800 (Wed, 31 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/awt/Component.java trunk/core/src/classpath/java/java/awt/Container.java trunk/core/src/classpath/java/java/awt/ContainerOrderFocusTraversalPolicy.java trunk/core/src/classpath/java/java/awt/EventDispatchThread.java trunk/core/src/classpath/java/java/awt/EventQueue.java trunk/core/src/classpath/java/java/awt/LightweightDispatcher.java trunk/core/src/classpath/java/java/awt/Window.java Modified: trunk/core/src/classpath/java/java/awt/Component.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Component.java 2007-01-31 19:02:43 UTC (rev 3098) +++ trunk/core/src/classpath/java/java/awt/Component.java 2007-01-31 20:25:09 UTC (rev 3099) @@ -1486,7 +1486,40 @@ } } - /** + /** + * Sends notification to interested listeners about resizing and/or moving + * the component. If this component has interested + * component listeners or the corresponding event mask enabled, then + * COMPONENT_MOVED and/or COMPONENT_RESIZED events are posted to the event + * queue. + * + * @param resized true if the component has been resized, false otherwise + * @param moved true if the component has been moved, false otherwise + */ + void notifyReshape(boolean resized, boolean moved) + { + // Only post an event if this component actually has a listener + // or has this event explicitly enabled. + if (componentListener != null + || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0) + { + // Fire component event on this component. + if (moved) + { + ComponentEvent ce = new ComponentEvent(this, + ComponentEvent.COMPONENT_MOVED); + getToolkit().getSystemEventQueue().postEvent(ce); + } + if (resized) + { + ComponentEvent ce = new ComponentEvent(this, + ComponentEvent.COMPONENT_RESIZED); + getToolkit().getSystemEventQueue().postEvent(ce); + } + } + } + + /** * Sets the bounding rectangle for this component to the specified * rectangle. Note that these coordinates are relative to the parent, not * to the screen. Modified: trunk/core/src/classpath/java/java/awt/Container.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Container.java 2007-01-31 19:02:43 UTC (rev 3098) +++ trunk/core/src/classpath/java/java/awt/Container.java 2007-01-31 20:25:09 UTC (rev 3099) @@ -1808,6 +1808,11 @@ } } + /** + * Overridden to dispatch events to lightweight descendents. + * + * @param e the event to dispatch. + */ void dispatchEventImpl(AWTEvent e) { boolean dispatched = @@ -1825,6 +1830,19 @@ } /** + * This is called by the lightweight dispatcher to avoid recursivly + * calling into the lightweight dispatcher. + * + * @param e the event to dispatch + * + * @see LightweightDispatcher#redispatch(MouseEvent, Component, int) + */ + void dispatchNoLightweight(AWTEvent e) + { + super.dispatchEventImpl(e); + } + + /** * Tests if this container has an interest in the given event id. * * @param eventId The event id to check. @@ -1938,6 +1956,43 @@ parent.updateHierarchyListenerCount(type, delta); } + /** + * Notifies interested listeners about resizing or moving the container. + * This performs the super behaviour (sending component events) and + * additionally notifies any hierarchy bounds listeners on child components. + * + * @param resized true if the component has been resized, false otherwise + * @param moved true if the component has been moved, false otherwise + */ + void notifyReshape(boolean resized, boolean moved) + { + // Notify component listeners. + super.notifyReshape(resized, moved); + + if (ncomponents > 0) + { + // Notify hierarchy bounds listeners. + if (resized) + { + for (int i = 0; i < getComponentCount(); i++) + { + Component child = getComponent(i); + child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED, + this, parent, 0); + } + } + if (moved) + { + for (int i = 0; i < getComponentCount(); i++) + { + Component child = getComponent(i); + child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED, + this, parent, 0); + } + } + } + } + private void addNotifyContainerChildren() { synchronized (getTreeLock ()) Modified: trunk/core/src/classpath/java/java/awt/ContainerOrderFocusTraversalPolicy.java =================================================================== --- trunk/core/src/classpath/java/java/awt/ContainerOrderFocusTraversalPolicy.java 2007-01-31 19:02:43 UTC (rev 3098) +++ trunk/core/src/classpath/java/java/awt/ContainerOrderFocusTraversalPolicy.java 2007-01-31 20:25:09 UTC (rev 3099) @@ -346,29 +346,31 @@ || !root.isDisplayable ()) return null; - if (root.visible && root.isDisplayable() && root.enabled - && root.focusable) + if (accept(root)) return root; - Component[] componentArray = root.getComponents (); - - for (int i = 0; i < componentArray.length; i++) + int ncomponents = root.getComponentCount(); + for (int i = 0; i < ncomponents; i++) { - Component component = componentArray [i]; - - if (component.visible && component.isDisplayable() && component.enabled - && component.focusable) - return component; - - if (component instanceof Container) + Component component = root.getComponent(i); + if (component instanceof Container + && !((Container) component).isFocusCycleRoot()) { - Component result = getFirstComponent ((Container) component); - - if (result != null - && (result.visible && result.isDisplayable() && result.enabled && result.focusable)) - return result; + Component first = null; + Container cont = (Container) component; + if (cont.isFocusTraversalPolicyProvider()) + { + FocusTraversalPolicy childPol = cont.getFocusTraversalPolicy(); + first = childPol.getFirstComponent(cont); } + else + first = getFirstComponent(cont); + if (first != null) + return first; } + else if (accept(component)) + return component; + } return null; } Modified: trunk/core/src/classpath/java/java/awt/EventDispatchThread.java =================================================================== --- trunk/core/src/classpath/java/java/awt/EventDispatchThread.java 2007-01-31 19:02:43 UTC (rev 3098) +++ trunk/core/src/classpath/java/java/awt/EventDispatchThread.java 2007-01-31 20:25:09 UTC (rev 3099) @@ -73,6 +73,9 @@ // Ignore and use default. } setPriority(priority); + + // Make sure that an event dispatch thread is never a daemon thread. + setDaemon(false); } public void run() Modified: trunk/core/src/classpath/java/java/awt/EventQueue.java =================================================================== --- trunk/core/src/classpath/java/java/awt/EventQueue.java 2007-01-31 19:02:43 UTC (rev 3098) +++ trunk/core/src/classpath/java/java/awt/EventQueue.java 2007-01-31 20:25:09 UTC (rev 3099) @@ -39,6 +39,7 @@ package java.awt; import gnu.java.awt.LowPriorityEvent; +import gnu.java.awt.peer.NativeEventLoopRunningEvent; import java.awt.event.ActionEvent; import java.awt.event.InputEvent; @@ -114,6 +115,7 @@ private long lastWhen = System.currentTimeMillis(); private EventDispatchThread dispatchThread = new EventDispatchThread(this); + private boolean nativeLoopRunning = false; private boolean shutdown = false; // @vm-specific allow JNode access from VMAwtAPI @@ -130,17 +132,19 @@ // This is the exact self-shutdown condition specified in J2SE: // http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/AWTThreadIssues.html - - // FIXME: check somewhere that the native queue is empty - if (peekEvent() == null) - { - Frame[] frames = Frame.getFrames(); - for (int i = 0; i < frames.length; ++i) - if (frames[i].isDisplayable()) - return false; - return true; - } + + if (nativeLoopRunning) return false; + + if (peekEvent() != null) + return false; + + Frame[] frames = Frame.getFrames(); + for (int i = 0; i < frames.length; ++i) + if (frames[i].isDisplayable()) + return false; + + return true; } /** @@ -169,22 +173,26 @@ return next.getNextEvent(); AWTEvent res = getNextEventImpl(true); + while (res == null) { - // We are not allowed to return null from this method, yet it - // is possible that we actually have run out of native events - // in the enclosing while() loop, and none of the native events - // happened to cause AWT events. We therefore ought to check - // the isShutdown() condition here, before risking a "native - // wait". If we check it before entering this function we may - // wait forever for events after the shutdown condition has - // arisen. + if (isShutdown()) + { + // Explicitly set dispathThread to null. If we don't do + // this, there is a race condition where dispatchThread + // can be != null even after the event dispatch thread has + // stopped running. If that happens, then the + // dispatchThread == null check in postEventImpl will + // fail, and a new event dispatch thread will not be + // created, leaving invokeAndWaits waiting indefinitely. + dispatchThread = null; - if (isShutdown()) + // Interrupt the event dispatch thread. throw new InterruptedException(); + } wait(); - res = getNextEventImpl(true); + res = getNextEventImpl(true); } return res; @@ -298,6 +306,12 @@ priority = LOW_PRIORITY; // TODO: Maybe let Swing RepaintManager events also be processed with // low priority. + if (evt instanceof NativeEventLoopRunningEvent) + { + nativeLoopRunning = ((NativeEventLoopRunningEvent) evt).isRunning(); + notify(); + return; + } postEventImpl(evt, priority); } Modified: trunk/core/src/classpath/java/java/awt/LightweightDispatcher.java =================================================================== --- trunk/core/src/classpath/java/java/awt/LightweightDispatcher.java 2007-01-31 19:02:43 UTC (rev 3098) +++ trunk/core/src/classpath/java/java/awt/LightweightDispatcher.java 2007-01-31 20:25:09 UTC (rev 3099) @@ -38,7 +38,10 @@ package java.awt; +import java.awt.event.InputEvent; import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.peer.LightweightPeer; import java.util.WeakHashMap; /** @@ -49,7 +52,7 @@ * * @author Roman Kennke (ke...@ai...) */ -class LightweightDispatcher +final class LightweightDispatcher { /** @@ -80,6 +83,11 @@ private Component lastTarget; /** + * The current mouseEventTarget. + */ + private Component mouseEventTarget; + + /** * Returns an instance of LightweightDispatcher for the current thread's * thread group. * @@ -113,7 +121,7 @@ * * @param event the event */ - public boolean dispatchEvent(AWTEvent event) + public boolean dispatchEvent(final AWTEvent event) { if (event instanceof MouseEvent && event.getSource() instanceof Window) { @@ -336,4 +344,138 @@ p.y -= offY; return p; } + + /** + * Checks if the specified component would be interested in a mouse event. + * + * @param c the component to check + * + * @return <code>true</code> if the component has mouse listeners installed, + * <code>false</code> otherwise + */ + private boolean isMouseListening(final Component c) + { + // Note: It is important to NOT check if the component is listening + // for a specific event (for instance, mouse motion events). The event + // gets dispatched to the component if the component is listening + // for ANY mouse event, even when the component is not listening for the + // specific type of event. There are applications that depend on this + // (sadly). + return c.mouseListener != null + || c.mouseMotionListener != null + || c.mouseWheelListener != null + || (c.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0 + || (c.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0 + || (c.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0; + } + + /** + * Tracks MOUSE_ENTERED and MOUSE_EXIT as well as MOUSE_MOVED and + * MOUSE_DRAGGED and creates synthetic MOUSE_ENTERED and MOUSE_EXITED for + * lightweight component.s + * + * @param target the current mouse event target + * @param ev the mouse event + */ + private void trackEnterExit(final Component target, final MouseEvent ev) + { + int id = ev.getID(); + if (target != lastTarget) + { + if (lastTarget != null) + redispatch(ev, lastTarget, MouseEvent.MOUSE_EXITED); + if (id == MouseEvent.MOUSE_EXITED) + ev.consume(); + if (target != null) + redispatch(ev, target, MouseEvent.MOUSE_ENTERED); + if (id == MouseEvent.MOUSE_ENTERED) + ev.consume(); + lastTarget = target; + } + + } + + /** + * Redispatches the specified mouse event to the specified target with the + * specified id. + * + * @param ev the mouse event + * @param target the new target + * @param id the new id + */ + private void redispatch(MouseEvent ev, Component target, int id) + { + Component source = ev.getComponent(); + if (target != null) + { + // Translate coordinates. + int x = ev.getX(); + int y = ev.getY(); + for (Component c = target; c != null && c != source; c = c.getParent()) + { + x -= c.x; + y -= c.y; + } + + // Retarget event. + MouseEvent retargeted; + if (id == MouseEvent.MOUSE_WHEEL) + { + MouseWheelEvent mwe = (MouseWheelEvent) ev; + retargeted = new MouseWheelEvent(target, id, ev.getWhen(), + ev.getModifiers() + | ev.getModifiersEx(), x, y, + ev.getClickCount(), + ev.isPopupTrigger(), + mwe.getScrollType(), + mwe.getScrollAmount(), + mwe.getWheelRotation()); + } + else + { + retargeted = new MouseEvent(target, id, ev.getWhen(), + ev.getModifiers() | ev.getModifiersEx(), + x, y, ev.getClickCount(), + ev.isPopupTrigger(), ev.getButton()); + } + + if (target == source) + ((Container) target).dispatchNoLightweight(retargeted); + else + target.dispatchEvent(retargeted); + } + } + + /** + * Determines if we are in the middle of a drag operation, that is, if + * any of the buttons is held down. + * + * @param ev the mouse event to check + * + * @return <code>true</code> if we are in the middle of a drag operation, + * <code>false</code> otherwise + */ + private boolean isDragging(MouseEvent ev) + { + int mods = ev.getModifiersEx(); + int id = ev.getID(); + if (id == MouseEvent.MOUSE_PRESSED || id == MouseEvent.MOUSE_RELEASED) + { + switch (ev.getButton()) + { + case MouseEvent.BUTTON1: + mods ^= InputEvent.BUTTON1_DOWN_MASK; + break; + case MouseEvent.BUTTON2: + mods ^= InputEvent.BUTTON2_DOWN_MASK; + break; + case MouseEvent.BUTTON3: + mods ^= InputEvent.BUTTON3_DOWN_MASK; + break; + } + } + return (mods & (InputEvent.BUTTON1_DOWN_MASK + | InputEvent.BUTTON2_DOWN_MASK + | InputEvent.BUTTON3_DOWN_MASK)) != 0; + } } Modified: trunk/core/src/classpath/java/java/awt/Window.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Window.java 2007-01-31 19:02:43 UTC (rev 3098) +++ trunk/core/src/classpath/java/java/awt/Window.java 2007-01-31 20:25:09 UTC (rev 3099) @@ -329,6 +329,15 @@ if (initialFocusOwner != null) initialFocusOwner.requestFocusInWindow(); + // Post WINDOW_OPENED from here. + if (windowListener != null + || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0) + { + WindowEvent ev = new WindowEvent(this, + WindowEvent.WINDOW_OPENED); + Toolkit tk = Toolkit.getDefaultToolkit(); + tk.getSystemEventQueue().postEvent(ev); + } shown = true; } } @@ -413,11 +422,8 @@ public void toFront() { if (peer != null) - { - WindowPeer wp = (WindowPeer) peer; - wp.toFront(); + ( (WindowPeer) peer ).toFront(); } - } /** * Returns the toolkit used to create this window. @@ -1146,6 +1152,47 @@ this.focusableWindowState = focusableWindowState; } + /** + * Check whether this Container is a focus cycle root. + * Returns always <code>true</code> as Windows are the + * root of the focus cycle. + * + * @return Always <code>true</code>. + * + * @since 1.4 + */ + public final boolean isFocusCycleRoot() + { + return true; + } + + /** + * Set whether or not this Container is the root of a focus + * traversal cycle. Windows are the root of the focus cycle + * and therefore this method does nothing. + * + * @param focusCycleRoot ignored. + * + * @since 1.4 + */ + public final void setFocusCycleRoot(boolean focusCycleRoot) + { + // calls to the method are ignored + } + + /** + * Returns the root container that owns the focus cycle where this + * component resides. Windows have no ancestors and this method + * returns always <code>null</code>. + * + * @return Always <code>null</code>. + * @since 1.4 + */ + public final Container getFocusCycleRootAncestor() + { + return null; + } + // setBoundsCallback is needed so that when a user moves a window, // the Window's location can be updated without calling the peer's // setBounds method. When a user moves a window the peer window's This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-31 19:02:54
|
Revision: 3098 http://jnode.svn.sourceforge.net/jnode/?rev=3098&view=rev Author: lsantha Date: 2007-01-31 11:02:43 -0800 (Wed, 31 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/awt/Choice.java trunk/core/src/classpath/java/java/awt/Component.java trunk/core/src/classpath/java/java/awt/Container.java trunk/core/src/classpath/java/java/awt/Frame.java trunk/core/src/classpath/java/java/awt/Label.java trunk/core/src/classpath/java/java/awt/List.java trunk/core/src/classpath/java/java/awt/Menu.java trunk/core/src/classpath/java/java/awt/ScrollPane.java trunk/core/src/classpath/java/java/awt/ScrollPaneAdjustable.java trunk/core/src/classpath/java/java/awt/Scrollbar.java trunk/core/src/classpath/java/java/awt/Window.java Modified: trunk/core/src/classpath/java/java/awt/Choice.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Choice.java 2007-01-28 21:36:49 UTC (rev 3097) +++ trunk/core/src/classpath/java/java/awt/Choice.java 2007-01-31 19:02:43 UTC (rev 3098) @@ -1,5 +1,5 @@ /* Choice.java -- Java choice button widget. - Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2002, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -58,35 +58,31 @@ public class Choice extends Component implements ItemSelectable, Serializable, Accessible { - -/* - * Static Variables + /** + * The number used to generate the name returned by getName. */ + private static transient long next_choice_number; -// Serialization constant -private static final long serialVersionUID = -4075310674757313071L; + // Serialization constant + private static final long serialVersionUID = -4075310674757313071L; -/*************************************************************************/ - -/* - * Instance Variables - */ - -/** + /** * @serial A list of items for the choice box, which can be <code>null</code>. * This is package-private to avoid an accessor method. */ -Vector pItems = new Vector(); + Vector pItems = new Vector(); -/** + /** * @serial The index of the selected item in the choice box. */ -private int selectedIndex = -1; + private int selectedIndex = -1; -// Listener chain -private ItemListener item_listeners; + /** + * ItemListener chain + */ + private ItemListener item_listeners; -/** + /** * This class provides accessibility support for the * combo box. * @@ -181,19 +177,12 @@ if (i < 0 || i >= pItems.size()) return false; - Choice.this.processItemEvent(new ItemEvent(Choice.this, - ItemEvent.ITEM_STATE_CHANGED, - this, ItemEvent.SELECTED)); + Choice.this.select( i ); + return true; } } -/*************************************************************************/ - -/* - * Constructors - */ - /** * Initializes a new instance of <code>Choice</code>. * @@ -206,56 +195,41 @@ throw new HeadlessException (); } -/*************************************************************************/ - -/* - * Instance Methods - */ - -/** + /** * Returns the number of items in the list. * * @return The number of items in the list. */ -public int -getItemCount() -{ + public int getItemCount() + { return countItems (); -} + } -/*************************************************************************/ - -/** + /** * Returns the number of items in the list. * * @return The number of items in the list. * * @deprecated This method is deprecated in favor of <code>getItemCount</code>. */ -public int -countItems() -{ - return(pItems.size()); -} + public int countItems() + { + return pItems.size(); + } -/*************************************************************************/ - -/** + /** * Returns the item at the specified index in the list. * * @param index The index into the list to return the item from. * * @exception ArrayIndexOutOfBoundsException If the index is invalid. */ -public String -getItem(int index) -{ - return((String)pItems.elementAt(index)); -} + public String getItem(int index) + { + return (String)pItems.elementAt(index); + } -/*************************************************************************/ - -/** + /** * Adds the specified item to this choice box. * * @param item The item to add. @@ -264,45 +238,36 @@ * * @since 1.1 */ -public synchronized void -add(String item) -{ + public synchronized void add(String item) + { if (item == null) throw new NullPointerException ("item must be non-null"); pItems.addElement(item); - int i = pItems.size () - 1; if (peer != null) - { - ChoicePeer cp = (ChoicePeer) peer; - cp.add (item, i); - } - else if (selectedIndex == -1) - select(0); -} + ((ChoicePeer) peer).add(item, getItemCount() - 1); -/*************************************************************************/ + if (selectedIndex == -1) + select( 0 ); + } -/** + /** * Adds the specified item to this choice box. * - * This method is oboslete since Java 2 platform 1.1. Please use @see add - * instead. + * This method is oboslete since Java 2 platform 1.1. Please use + * {@link #add(String)} instead. * * @param item The item to add. * * @exception NullPointerException If the item's value is equal to null */ -public synchronized void -addItem(String item) -{ + public synchronized void addItem(String item) + { add(item); -} + } -/*************************************************************************/ - -/** Inserts an item into this Choice. Existing items are shifted + /** Inserts an item into this Choice. Existing items are shifted * upwards. If the new item is the only item, then it is selected. * If the currently selected item is shifted, then the first item is * selected. If the currently selected item is not shifted, then it @@ -313,9 +278,8 @@ * * @exception IllegalArgumentException If index is less than 0 */ -public synchronized void -insert(String item, int index) -{ + public synchronized void insert(String item, int index) + { if (index < 0) throw new IllegalArgumentException ("index may not be less then 0"); @@ -325,75 +289,61 @@ pItems.insertElementAt(item, index); if (peer != null) - { - ChoicePeer cp = (ChoicePeer) peer; - cp.add (item, index); - } - else if (selectedIndex == -1 || selectedIndex >= index) + ((ChoicePeer) peer).add (item, index); + + if (selectedIndex == -1 || selectedIndex >= index) select(0); -} + } -/*************************************************************************/ - -/** + /** * Removes the specified item from the choice box. * * @param item The item to remove. * * @exception IllegalArgumentException If the specified item doesn't exist. */ -public synchronized void -remove(String item) -{ + public synchronized void remove(String item) + { int index = pItems.indexOf(item); if (index == -1) throw new IllegalArgumentException ("item \"" + item + "\" not found in Choice"); remove(index); -} + } -/*************************************************************************/ - -/** + /** * Removes the item at the specified index from the choice box. * * @param index The index of the item to remove. * * @exception IndexOutOfBoundsException If the index is not valid. */ -public synchronized void -remove(int index) -{ - if ((index < 0) || (index > getItemCount())) - throw new IllegalArgumentException("Bad index: " + index); - + public synchronized void remove(int index) + { pItems.removeElementAt(index); if (peer != null) - { - ChoicePeer cp = (ChoicePeer) peer; - cp.remove (index); - } - else - { - if (getItemCount() == 0) + ((ChoicePeer) peer).remove( index ); + + if( getItemCount() == 0 ) selectedIndex = -1; - else if (index == selectedIndex) - select(0); - } + else + { + if( selectedIndex > index ) + selectedIndex--; + else if( selectedIndex == index ) + selectedIndex = 0; - if (selectedIndex > index) - --selectedIndex; -} + if( peer != null ) + ((ChoicePeer)peer).select( selectedIndex ); + } + } -/*************************************************************************/ - -/** + /** * Removes all of the objects from this choice box. */ -public synchronized void -removeAll() -{ + public synchronized void removeAll() + { if (getItemCount() <= 0) return; @@ -406,197 +356,159 @@ } selectedIndex = -1; -} + } -/*************************************************************************/ - -/** + /** * Returns the currently selected item, or null if no item is * selected. * * @return The currently selected item. */ -public synchronized String -getSelectedItem() -{ + public synchronized String getSelectedItem() + { return (selectedIndex == -1 ? null : ((String)pItems.elementAt(selectedIndex))); -} + } -/*************************************************************************/ - -/** + /** * Returns an array with one row containing the selected item. * * @return An array containing the selected item. */ -public synchronized Object[] -getSelectedObjects() -{ + public synchronized Object[] getSelectedObjects() + { if (selectedIndex == -1) return null; Object[] objs = new Object[1]; objs[0] = pItems.elementAt(selectedIndex); - return(objs); -} + return objs; + } -/*************************************************************************/ - -/** + /** * Returns the index of the selected item. * * @return The index of the selected item. */ -public int -getSelectedIndex() -{ - return(selectedIndex); -} + public int getSelectedIndex() + { + return selectedIndex; + } -/*************************************************************************/ - -/** + /** * Forces the item at the specified index to be selected. * * @param index The index of the row to make selected. * * @exception IllegalArgumentException If the specified index is invalid. */ -public synchronized void -select(int index) -{ + public synchronized void select(int index) + { if ((index < 0) || (index >= getItemCount())) throw new IllegalArgumentException("Bad index: " + index); - if (pItems.size() > 0) { + if( selectedIndex == index ) + return; + selectedIndex = index; - ChoicePeer cp = (ChoicePeer) peer; - if (cp != null) { - cp.select(index); + if( peer != null ) + ((ChoicePeer)peer).select( index ); } - } -} -/*************************************************************************/ - -/** + /** * Forces the named item to be selected. * * @param item The item to be selected. * * @exception IllegalArgumentException If the specified item does not exist. */ -public synchronized void -select(String item) -{ + public synchronized void select(String item) + { int index = pItems.indexOf(item); - if (index >= 0) - select(index); -} + if( index >= 0 ) + select( index ); + } -/*************************************************************************/ - -/** + /** * Creates the native peer for this object. */ -public void -addNotify() -{ + public void addNotify() + { if (peer == null) peer = getToolkit ().createChoice (this); super.addNotify (); -} + } -/*************************************************************************/ - -/** + /** * Adds the specified listener to the list of registered listeners for * this object. * * @param listener The listener to add. */ -public synchronized void -addItemListener(ItemListener listener) -{ + public synchronized void addItemListener(ItemListener listener) + { item_listeners = AWTEventMulticaster.add(item_listeners, listener); -} + } -/*************************************************************************/ - -/** + /** * Removes the specified listener from the list of registered listeners for * this object. * * @param listener The listener to remove. */ -public synchronized void -removeItemListener(ItemListener listener) -{ + public synchronized void removeItemListener(ItemListener listener) + { item_listeners = AWTEventMulticaster.remove(item_listeners, listener); -} + } -/*************************************************************************/ - -/** + /** * Processes this event by invoking <code>processItemEvent()</code> if the * event is an instance of <code>ItemEvent</code>, otherwise the event * is passed to the superclass. * * @param event The event to process. */ -protected void -processEvent(AWTEvent event) -{ + protected void processEvent(AWTEvent event) + { if (event instanceof ItemEvent) processItemEvent((ItemEvent)event); else super.processEvent(event); -} + } -void -dispatchEventImpl(AWTEvent e) -{ - if (e.id <= ItemEvent.ITEM_LAST - && e.id >= ItemEvent.ITEM_FIRST - && (item_listeners != null || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0)) - processEvent(e); - else + void dispatchEventImpl(AWTEvent e) + { super.dispatchEventImpl(e); -} -/*************************************************************************/ + if( e.id <= ItemEvent.ITEM_LAST && e.id >= ItemEvent.ITEM_FIRST && + ( item_listeners != null || + ( eventMask & AWTEvent.ITEM_EVENT_MASK ) != 0 ) ) + processEvent(e); + } -/** + /** * Processes item event by dispatching to any registered listeners. * * @param event The event to process. */ -protected void -processItemEvent(ItemEvent event) -{ + protected void processItemEvent(ItemEvent event) + { int index = pItems.indexOf((String) event.getItem()); - // Don't call back into the peers when selecting index here - if (event.getStateChange() == ItemEvent.SELECTED) - this.selectedIndex = index; if (item_listeners != null) item_listeners.itemStateChanged(event); -} + } -/*************************************************************************/ - -/** + /** * Returns a debugging string for this object. * * @return A debugging string for this object. */ -protected String -paramString() -{ - return ("selectedIndex=" + selectedIndex + "," + super.paramString()); -} + protected String paramString() + { + return "selectedIndex=" + selectedIndex + "," + super.paramString(); + } /** * Returns an array of all the objects currently registered as FooListeners @@ -608,7 +520,7 @@ * * @since 1.3 */ - public EventListener[] getListeners (Class listenerType) + public <T extends EventListener> T[] getListeners (Class<T> listenerType) { if (listenerType == ItemListener.class) return AWTEventMulticaster.getListeners (item_listeners, listenerType); @@ -639,4 +551,19 @@ accessibleContext = new AccessibleAWTChoice(); return accessibleContext; } -} // class Choice + + /** + * Generate a unique name for this <code>Choice</code>. + * + * @return A unique name for this <code>Choice</code>. + */ + String generateName() + { + return "choice" + getUniqueLong(); + } + + private static synchronized long getUniqueLong() + { + return next_choice_number++; + } +} // class Choice Modified: trunk/core/src/classpath/java/java/awt/Component.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Component.java 2007-01-28 21:36:49 UTC (rev 3097) +++ trunk/core/src/classpath/java/java/awt/Component.java 2007-01-31 19:02:43 UTC (rev 3098) @@ -39,6 +39,10 @@ package java.awt; +//import gnu.java.awt.dnd.peer.gtk.GtkDropTargetContextPeer; + +import gnu.java.awt.ComponentReshapeEvent; + import java.awt.dnd.DropTarget; import java.awt.event.ActionEvent; import java.awt.event.AdjustmentEvent; @@ -70,6 +74,7 @@ import java.awt.image.VolatileImage; import java.awt.peer.ComponentPeer; import java.awt.peer.LightweightPeer; +import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.IOException; @@ -213,6 +218,12 @@ */ static final Object treeLock = new String("AWT_TREE_LOCK"); + /** + * The default maximum size. + */ + private static final Dimension DEFAULT_MAX_SIZE + = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); + // Serialized fields from the serialization spec. /** @@ -427,6 +438,24 @@ Dimension minSize; /** + * Flag indicating whether the minimum size for the component has been set + * by a call to {@link #setMinimumSize(Dimension)} with a non-null value. + */ + boolean minSizeSet; + + /** + * The maximum size for the component. + * @see #setMaximumSize(Dimension) + */ + Dimension maxSize; + + /** + * A flag indicating whether the maximum size for the component has been set + * by a call to {@link #setMaximumSize(Dimension)} with a non-null value. + */ + boolean maxSizeSet; + + /** * Cached information on the preferred size. Should have been transient. * * @serial ignore @@ -569,6 +598,17 @@ transient BufferStrategy bufferStrategy; /** + * The number of hierarchy listeners of this container plus all of its + * children. This is needed for efficient handling of HierarchyEvents. + * These must be propagated to all child components with HierarchyListeners + * attached. To avoid traversal of the whole subtree, we keep track of + * the number of HierarchyListeners here and only walk the paths that + * actually have listeners. + */ + int numHierarchyListeners; + int numHierarchyBoundsListeners; + + /** * true if requestFocus was called on this component when its * top-level ancestor was not focusable. */ @@ -613,16 +653,19 @@ } /** - * Sets the name of this component to the specified name. + * Sets the name of this component to the specified name (this is a bound + * property with the name 'name'). * - * @param name the new name of this component + * @param name the new name (<code>null</code> permitted). * @see #getName() * @since 1.1 */ public void setName(String name) { nameExplicitlySet = true; + String old = this.name; this.name = name; + firePropertyChange("name", old, name); } /** @@ -659,6 +702,9 @@ public void setDropTarget(DropTarget dt) { this.dropTarget = dt; + + if (peer != null) + dropTarget.addNotify(peer); } /** @@ -1590,6 +1636,7 @@ * * @return the component's preferred size * @see #getMinimumSize() + * @see #setPreferredSize(Dimension) * @see LayoutManager */ public Dimension getPreferredSize() @@ -1600,7 +1647,7 @@ /** * Sets the preferred size that will be returned by * {@link #getPreferredSize()} always, and sends a - * {@link java.beans.PropertyChangeEvent} (with the property name 'preferredSize') to + * {@link PropertyChangeEvent} (with the property name 'preferredSize') to * all registered listeners. * * @param size the preferred size (<code>null</code> permitted). @@ -1662,6 +1709,39 @@ } /** + * Sets the minimum size that will be returned by {@link #getMinimumSize()} + * always, and sends a {@link PropertyChangeEvent} (with the property name + * 'minimumSize') to all registered listeners. + * + * @param size the minimum size (<code>null</code> permitted). + * + * @since 1.5 + * + * @see #getMinimumSize() + */ + public void setMinimumSize(Dimension size) + { + Dimension old = minSizeSet ? minSize : null; + minSize = size; + minSizeSet = (size != null); + firePropertyChange("minimumSize", old, size); + } + + /** + * Returns <code>true</code> if the current minimum size is not + * <code>null</code> and was set by a call to + * {@link #setMinimumSize(Dimension)}, otherwise returns <code>false</code>. + * + * @return A boolean. + * + * @since 1.5 + */ + public boolean isMinimumSizeSet() + { + return minSizeSet; + } + + /** * Returns the component's minimum size. * * @return the component's minimum size @@ -1676,10 +1756,38 @@ } /** + * The actual calculation is pulled out of minimumSize() so that + * we can call it from Container.preferredSize() and + * Component.preferredSizeImpl and avoid creating a + * new intermediate Dimension object. + * + * @return the minimum size of the component + */ + Dimension minimumSizeImpl() + { + Dimension size = minSize; + if (size == null || !(valid || minSizeSet)) + { + // We need to lock here, because the calculation depends on the + // component structure not changing. + synchronized (getTreeLock()) + { + ComponentPeer p = peer; + if (p != null) + size = peer.minimumSize(); + else + size = size(); + } + } + return size; + } + + /** * Returns the component's maximum size. * * @return the component's maximum size * @see #getMinimumSize() + * @see #setMaximumSize(Dimension) * @see #getPreferredSize() * @see LayoutManager */ @@ -1689,6 +1797,56 @@ } /** + * This is pulled out from getMaximumSize(), so that we can access it + * from Container.getMaximumSize() without creating an additional + * intermediate Dimension object. + * + * @return the maximum size of the component + */ + Dimension maximumSizeImpl() + { + Dimension size; + if (maxSizeSet) + size = maxSize; + else + size = DEFAULT_MAX_SIZE; + return size; + } + + /** + * Sets the maximum size that will be returned by {@link #getMaximumSize()} + * always, and sends a {@link PropertyChangeEvent} (with the property name + * 'maximumSize') to all registered listeners. + * + * @param size the maximum size (<code>null</code> permitted). + * + * @since 1.5 + * + * @see #getMaximumSize() + */ + public void setMaximumSize(Dimension size) + { + Dimension old = maxSizeSet ? maxSize : null; + maxSize = size; + maxSizeSet = (size != null); + firePropertyChange("maximumSize", old, size); + } + + /** + * Returns <code>true</code> if the current maximum size is not + * <code>null</code> and was set by a call to + * {@link #setMaximumSize(Dimension)}, otherwise returns <code>false</code>. + * + * @return A boolean. + * + * @since 1.5 + */ + public boolean isMaximumSizeSet() + { + return maxSizeSet; + } + + /** * Returns the preferred horizontal alignment of this component. The value * returned will be between {@link #LEFT_ALIGNMENT} and * {@link #RIGHT_ALIGNMENT}, inclusive. @@ -1873,11 +2031,9 @@ } /** - * Updates this component. This is called in response to - * <code>repaint</code>. This method fills the component with the - * background color, then sets the foreground color of the specified - * graphics context to the foreground color of this component and calls - * the <code>paint()</code> method. The coordinates of the graphics are + * Updates this component. This is called for heavyweight components in + * response to {@link #repaint()}. The default implementation simply forwards + * to {@link #paint(Graphics)}. The coordinates of the graphics are * relative to this component. Subclasses should call either * <code>super.update(g)</code> or <code>paint(g)</code>. * @@ -1885,11 +2041,6 @@ * * @see #paint(Graphics) * @see #repaint() - * - * @specnote In contrast to what the spec says, tests show that the exact - * behaviour is to clear the background on lightweight and - * top-level components only. Heavyweight components are not - * affected by this method and only call paint(). */ public void update(Graphics g) { @@ -2004,10 +2155,7 @@ } /** - * Prints this component, including all sub-components. This method is - * provided so that printing can be done in a different manner from - * painting. However, the implementation in this class simply calls the - * <code>paintAll()</code> method. + * Prints this component, including all sub-components. * * @param g the graphics context of the print device * @@ -2365,6 +2513,17 @@ } /** + * By default, no old mouse events should be ignored. + * This can be overridden by subclasses. + * + * @return false, no mouse events are ignored. + */ + static boolean ignoreOldMouseEvents() + { + return false; + } + + /** * AWT 1.0 event handler. * * This method simply calls handleEvent and returns the result. @@ -2581,6 +2740,40 @@ } /** + * Fires a HierarchyEvent or HierarchyChangeEvent on this component. + * + * @param id the event id + * @param changed the changed component + * @param parent the parent + * @param flags the event flags + */ + void fireHierarchyEvent(int id, Component changed, Container parent, + long flags) + { + boolean enabled = false; + switch (id) + { + case HierarchyEvent.HIERARCHY_CHANGED: + enabled = hierarchyListener != null + || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0; + break; + case HierarchyEvent.ANCESTOR_MOVED: + case HierarchyEvent.ANCESTOR_RESIZED: + enabled = hierarchyBoundsListener != null + || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0; + break; + default: + assert false : "Should not reach here"; + } + if (enabled) + { + HierarchyEvent ev = new HierarchyEvent(this, id, changed, parent, + flags); + dispatchEvent(ev); + } + } + + /** * Adds the specified listener to this component. This is harmless if the * listener is null, but if the listener has already been registered, it * will now be registered twice. @@ -3636,7 +3829,8 @@ * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS * @since 1.4 */ - public void setFocusTraversalKeys(int id, Set keystrokes) + public void setFocusTraversalKeys(int id, + Set<? extends AWTKeyStroke> keystrokes) { if (keystrokes == null) { @@ -3728,14 +3922,14 @@ * * @since 1.4 */ - public Set getFocusTraversalKeys (int id) + public Set<AWTKeyStroke> getFocusTraversalKeys (int id) { if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS) throw new IllegalArgumentException(); - Set s = null; + Set<AWTKeyStroke> s = null; if (focusTraversalKeys != null) s = focusTraversalKeys[id]; @@ -4740,8 +4934,7 @@ * {@link #applyComponentOrientation(ComponentOrientation)} affects the * entire hierarchy. * - * @param o the new orientation - * @throws NullPointerException if o is null + * @param o the new orientation (<code>null</code> is accepted) * @see #getComponentOrientation() */ public void setComponentOrientation(ComponentOrientation o) @@ -4756,7 +4949,7 @@ /** * Determines the text layout orientation used by this component. * - * @return the component orientation + * @return the component orientation (this can be <code>null</code>) * @see #setComponentOrientation(ComponentOrientation) */ public ComponentOrientation getComponentOrientation() @@ -5046,7 +5239,7 @@ oldKey = Event.UP; break; default: - oldKey = (int) ((KeyEvent) e).getKeyChar(); + oldKey = ((KeyEvent) e).getKeyChar(); } translated = new Event (target, when, oldID, @@ -5089,11 +5282,10 @@ * * @param e the event to dispatch */ - void dispatchEventImpl(AWTEvent e) { - // This boolean tells us not to process focus events when the focus - // opposite component is the same as the focus component. + // Update the component's knowledge about the size. + // Important: Please look at the big comment in ComponentReshapeEvent boolean ignoreFocus = (e instanceof FocusEvent && ((FocusEvent)e).getComponent() == ((FocusEvent)e).getOppositeComponent()); @@ -5385,7 +5577,7 @@ */ public void componentHidden(ComponentEvent event) { - if (!isShowing()) + if (isShowing()) peer.hide(); } } Modified: trunk/core/src/classpath/java/java/awt/Container.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Container.java 2007-01-28 21:36:49 UTC (rev 3097) +++ trunk/core/src/classpath/java/java/awt/Container.java 2007-01-31 19:02:43 UTC (rev 3098) @@ -42,7 +42,9 @@ import java.awt.event.ComponentListener; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; +import java.awt.event.HierarchyEvent; import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; import java.awt.peer.ComponentPeer; import java.awt.peer.ContainerPeer; import java.awt.peer.LightweightPeer; @@ -68,10 +70,11 @@ * * @author original author unknown * @author Eric Blake (eb...@em...) + * @author Andrew John Hughes (gnu...@me...) * * @since 1.0 * - * @status still missing 1.4 support + * @status still missing 1.4 support, some generics from 1.5 */ public class Container extends Component { @@ -97,6 +100,13 @@ */ boolean focusCycleRoot; + /** + * Indicates if this container provides a focus traversal policy. + * + * @since 1.5 + */ + private boolean focusTraversalPolicyProvider; + int containerSerializedDataVersion; /* Anything else is non-serializable, and should be declared "transient". */ @@ -927,10 +937,10 @@ * * @since 1.3 */ - public EventListener[] getListeners(Class listenerType) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { if (listenerType == ContainerListener.class) - return getContainerListeners(); + return (T[]) getContainerListeners(); return super.getListeners(listenerType); } @@ -1549,6 +1559,42 @@ } /** + * Set to <code>true</code> if this container provides a focus traversal + * policy, <code>false</code> when the root container's focus + * traversal policy should be used. + * + * @return <code>true</code> if this container provides a focus traversal + * policy, <code>false</code> when the root container's focus + * traversal policy should be used + * + * @see #setFocusTraversalPolicyProvider(boolean) + * + * @since 1.5 + */ + public final boolean isFocusTraversalPolicyProvider() + { + return focusTraversalPolicyProvider; + } + + /** + * Set to <code>true</code> if this container provides a focus traversal + * policy, <code>false</code> when the root container's focus + * traversal policy should be used. + * + * @param b <code>true</code> if this container provides a focus traversal + * policy, <code>false</code> when the root container's focus + * traversal policy should be used + * + * @see #isFocusTraversalPolicyProvider() + * + * @since 1.5 + */ + public final void setFocusTraversalPolicyProvider(boolean b) + { + focusTraversalPolicyProvider = b; + } + + /** * Check whether this Container is a focus cycle root. * * @return true if this is a focus cycle root, false otherwise @@ -1850,6 +1896,48 @@ } } + /** + * Fires hierarchy events to the children of this container and this + * container itself. This overrides {@link Component#fireHierarchyEvent} + * in order to forward this event to all children. + */ + void fireHierarchyEvent(int id, Component changed, Container parent, + long flags) + { + // Only propagate event if there is actually a listener waiting for it. + if ((id == HierarchyEvent.HIERARCHY_CHANGED && numHierarchyListeners > 0) + || ((id == HierarchyEvent.ANCESTOR_MOVED + || id == HierarchyEvent.ANCESTOR_RESIZED) + && numHierarchyBoundsListeners > 0)) + { + for (int i = 0; i < ncomponents; i++) + component[i].fireHierarchyEvent(id, changed, parent, flags); + super.fireHierarchyEvent(id, changed, parent, flags); + } + } + + /** + * Adjusts the number of hierarchy listeners of this container and all of + * its parents. This is called by the add/remove listener methods and + * structure changing methods in Container. + * + * @param type the type, either {@link AWTEvent#HIERARCHY_BOUNDS_EVENT_MASK} + * or {@link AWTEvent#HIERARCHY_EVENT_MASK} + * @param delta the number of listeners added or removed + */ + void updateHierarchyListenerCount(long type, int delta) + { + if (type == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) + numHierarchyBoundsListeners += delta; + else if (type == AWTEvent.HIERARCHY_EVENT_MASK) + numHierarchyListeners += delta; + else + assert false : "Should not reach here"; + + if (parent != null) + parent.updateHierarchyListenerCount(type, delta); + } + private void addNotifyContainerChildren() { synchronized (getTreeLock ()) Modified: trunk/core/src/classpath/java/java/awt/Frame.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Frame.java 2007-01-28 21:36:49 UTC (rev 3097) +++ trunk/core/src/classpath/java/java/awt/Frame.java 2007-01-31 19:02:43 UTC (rev 3098) @@ -340,12 +340,15 @@ parent.remove(menuBar); menuBar.setParent(this); - if (peer != null) + // Create local copy for thread safety. + FramePeer p = (FramePeer) peer; + if (p != null) { if (menuBar != null) menuBar.addNotify(); - invalidateTree(); - ((FramePeer) peer).setMenuBar(menuBar); + if (valid) + invalidate(); + p.setMenuBar(menuBar); } } } @@ -485,8 +488,11 @@ private static void noteFrame(Frame f) { + synchronized (weakFrames) + { weakFrames.add(new WeakReference(f)); } + } public static Frame[] getFrames() { @@ -533,8 +539,7 @@ public int getState() { - // FIXME: State might have changed in the peer... Must check. - return (state & ICONIFIED) != 0 ? ICONIFIED : NORMAL; + return (getExtendedState() & ICONIFIED) != 0 ? ICONIFIED : NORMAL; } /** @@ -542,14 +547,23 @@ */ public void setExtendedState(int state) { + if (getToolkit().isFrameStateSupported(state)) + { this.state = state; + FramePeer p = (FramePeer) peer; + if (p != null) + p.setState(state); } + } /** * @since 1.4 */ public int getExtendedState() { + FramePeer p = (FramePeer) peer; + if (p != null) + state = p.getState(); return state; } Modified: trunk/core/src/classpath/java/java/awt/Label.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Label.java 2007-01-28 21:36:49 UTC (rev 3097) +++ trunk/core/src/classpath/java/java/awt/Label.java 2007-01-31 19:02:43 UTC (rev 3098) @@ -1,5 +1,6 @@ /* Label.java -- Java label widget - Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2002, 2004, 2005, 2006, Free Software + Foundation, Inc. This file is part of GNU Classpath. @@ -55,66 +56,47 @@ public class Label extends Component implements Accessible { -/* - * Static Variables - */ - -/** + /** * Alignment constant aligning the text to the left of its window. */ -public static final int LEFT = 0; + public static final int LEFT = 0; -/** + /** * Alignment constant aligning the text in the center of its window. */ -public static final int CENTER = 1; + public static final int CENTER = 1; -/** + /** * Alignment constant aligning the text to the right of its window. */ -public static final int RIGHT = 2; + public static final int RIGHT = 2; -// Serialization version constant: -private static final long serialVersionUID = 3094126758329070636L; + // Serialization version constant: + private static final long serialVersionUID = 3094126758329070636L; -/*************************************************************************/ - -/* - * Instance Variables - */ - -/** + /** * @serial Indicates the alignment of the text within this label's window. * This is one of the constants in this class. The default value is * <code>LEFT</code>. */ -private int alignment; + private int alignment; -/** + /** * @serial The text displayed in the label */ -private String text; + private String text; -/*************************************************************************/ - -/* - * Constructors - */ - -/** + /** * Initializes a new instance of <code>Label</code> with no text. * * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. */ -public -Label() -{ + public Label() + { this("", LEFT); -} + } -/*************************************************************************/ - -/** + /** * Initializes a new instance of <code>Label</code> with the specified * text that is aligned to the left. * @@ -122,15 +104,12 @@ * * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. */ -public -Label(String text) -{ + public Label(String text) + { this(text, LEFT); -} + } -/*************************************************************************/ - -/** + /** * Initializes a new instance of <code>Label</code> with the specified * text and alignment. * @@ -141,80 +120,63 @@ * * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. */ -public -Label(String text, int alignment) -{ - setAlignment (alignment); - setText (text); + public Label(String text, int alignment) + { + setAlignment(alignment); + setText(text); if (GraphicsEnvironment.isHeadless()) - throw new HeadlessException (); -} + throw new HeadlessException(); + } -/*************************************************************************/ - -/* - * Instance Variables - */ - -/** + /** * Returns the constant indicating the alignment of the text in this * label. The value returned will be one of the alignment constants * from this class. * * @return The alignment of the text in the label. */ -public int -getAlignment() -{ + public int getAlignment() + { return(alignment); -} + } -/*************************************************************************/ - -/** + /** * Sets the text alignment of this label to the specified value. * * @param alignment The desired alignment for the text in this label, * which must be one of <code>LEFT</code>, <code>CENTER</code>, or * <code>RIGHT</code>. */ -public synchronized void -setAlignment(int alignment) -{ + public synchronized void setAlignment(int alignment) + { if (alignment != CENTER && alignment != LEFT && alignment != RIGHT) - throw new IllegalArgumentException ("invalid alignment: " + alignment); + throw new IllegalArgumentException("invalid alignment: " + alignment); this.alignment = alignment; if (peer != null) { LabelPeer lp = (LabelPeer) peer; - lp.setAlignment (alignment); + lp.setAlignment(alignment); + } } -} -/*************************************************************************/ - -/** + /** * Returns the text displayed in this label. * * @return The text for this label. */ -public String -getText() -{ - return(text); -} + public String getText() + { + return text; + } -/*************************************************************************/ - -/** + /** * Sets the text in this label to the specified value. * * @param text The new text for this label. */ -public synchronized void -setText(String text) -{ + public synchronized void setText(String text) + { if ((this.text == null && text != null) || (this.text != null && ! this.text.equals(text))) { @@ -223,47 +185,41 @@ if (peer != null) { LabelPeer lp = (LabelPeer) peer; - lp.setText (text); + lp.setText(text); } invalidate(); } -} + } -/*************************************************************************/ - -/** + /** * Notifies this label that it has been added to a container, causing * the peer to be created. This method is called internally by the AWT * system. */ -public void -addNotify() -{ + public void addNotify() + { if (peer == null) - peer = getToolkit ().createLabel (this); - super.addNotify (); -} + peer = getToolkit().createLabel(this); + super.addNotify(); + } -/*************************************************************************/ - -/** + /** * Returns a parameter string useful for debugging. * * @return A debugging string. */ -protected String -paramString() -{ + protected String paramString() + { return ("text=" + getText() + ",alignment=" + getAlignment() + "," + super.paramString()); -} + } -/** + /** * This class provides accessibility support for the label. */ -protected class AccessibleAWTLabel + protected class AccessibleAWTLabel extends AccessibleAWTComponent -{ + { /** * For compatability with Sun's JDK 1.4.2 rev. 5 */ @@ -299,21 +255,41 @@ return AccessibleRole.LABEL; } -} + } -/** + /** * Gets the AccessibleContext associated with this <code>Label</code>. * The context is created, if necessary. * * @return the associated context */ -public AccessibleContext getAccessibleContext() -{ + public AccessibleContext getAccessibleContext() + { /* Create the context if this is the first request */ if (accessibleContext == null) accessibleContext = new AccessibleAWTLabel(); return accessibleContext; -} + } -} // class Label + /** + * Generate a unique name for this button. + * + * @return A unique name for this button. + */ + String generateName() + { + return "label" + getUniqueLong(); + } + /** + * The number used to generate the name returned by getName. + */ + private static transient long nextLabelNumber; + + private static synchronized long getUniqueLong() + { + return nextLabelNumber++; + } + +} + Modified: trunk/core/src/classpath/java/java/awt/List.java =================================================================== --- trunk/core/src/classpath/java/java/awt/List.java 2007-01-28 21:36:49 UTC (rev 3097) +++ trunk/core/src/classpath/java/java/awt/List.java 2007-01-31 19:02:43 UTC (rev 3098) @@ -1,5 +1,5 @@ /* List.java -- A listbox widget - Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 1999, 2002, 2004, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -62,77 +62,63 @@ implements ItemSelectable, Accessible { -/* - * Static Variables + /** + * The number used to generate the name returned by getName. */ + private static transient long next_list_number; -// Serialization constant -private static final long serialVersionUID = -3304312411574666869L; + // Serialization constant + private static final long serialVersionUID = -3304312411574666869L; -/*************************************************************************/ + // FIXME: Need read/writeObject -/* - * Instance Variables - */ - -// FIXME: Need read/writeObject - -/** + /** * @serial The items in the list. */ -private Vector items = new Vector(); + private Vector items = new Vector(); -/** + /** * @serial Indicates whether or not multiple items can be selected * simultaneously. */ -private boolean multipleMode; + private boolean multipleMode; -/** + /** * @serial The number of rows in the list. This is set on creation * only and cannot be modified. */ -private int rows; + private int rows; -/** + /** * @serial An array of the item indices that are selected. */ -private int[] selected; + private int[] selected; -/** + /** * @serial An index value used by <code>makeVisible()</code> and * <code>getVisibleIndex</code>. */ -private int visibleIndex; + private int visibleIndex = -1; -// The list of ItemListeners for this object. -private ItemListener item_listeners; + // The list of ItemListeners for this object. + private ItemListener item_listeners; -// The list of ActionListeners for this object. -private ActionListener action_listeners; + // The list of ActionListeners for this object. + private ActionListener action_listeners; - -/*************************************************************************/ - -/* - * Constructors - */ - -/** + /** * Initializes a new instance of <code>List</code> with no visible lines * and multi-select disabled. * * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. + * @since 1.1 */ -public -List() -{ + public List() + { this(4, false); -} + } -/*************************************************************************/ - -/** + /** * Initializes a new instance of <code>List</code> with the specified * number of visible lines and multi-select disabled. * @@ -140,15 +126,12 @@ * * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. */ -public -List(int rows) -{ + public List(int rows) + { this(rows, false); -} + } -/*************************************************************************/ - -/** + /** * Initializes a new instance of <code>List</code> with the specified * number of lines and the specified multi-select setting. * @@ -158,37 +141,34 @@ * * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true. */ -public -List(int rows, boolean multipleMode) -{ + public List(int rows, boolean multipleMode) + { + if (rows == 0) + this.rows = 4; + else this.rows = rows; + this.multipleMode = multipleMode; selected = new int[0]; if (GraphicsEnvironment.isHeadless()) - throw new HeadlessException (); -} + throw new HeadlessException(); -/*************************************************************************/ + } -/* - * Instance Variables - */ - -/** + /** * Returns the number of items in this list. * * @return The number of items in this list. + * + * @since 1.1 */ -public int -getItemCount() -{ - return countItems (); -} + public int getItemCount() + { + return countItems(); + } -/*************************************************************************/ - -/** + /** * Returns the number of items in this list. * * @return The number of items in this list. @@ -196,73 +176,62 @@ * @deprecated This method is deprecated in favor of * <code>getItemCount()</code> */ -public int -countItems() -{ - return items.size (); -} + public int countItems() + { + return items.size(); + } -/*************************************************************************/ - -/** + /** * Returns the complete list of items. * * @return The complete list of items in the list. + * + * @since 1.1 */ -public synchronized String[] -getItems() -{ + public synchronized String[] getItems() + { String[] l_items = new String[getItemCount()]; items.copyInto(l_items); return(l_items); -} + } -/*************************************************************************/ - -/** + /** * Returns the item at the specified index. * * @param index The index of the item to retrieve. * * @exception IndexOutOfBoundsException If the index value is not valid. */ -public String -getItem(int index) -{ - return((String)items.elementAt(index)); -} + public String getItem(int index) + { + return((String) items.elementAt(index)); + } -/*************************************************************************/ - -/** + /** * Returns the number of visible rows in the list. * * @return The number of visible rows in the list. */ -public int -getRows() -{ + public int getRows() + { return(rows); -} + } -/*************************************************************************/ - -/** + /** * Tests whether or not multi-select mode is enabled. * * @return <code>true</code> if multi-select mode is enabled, * <code>false</code> otherwise. + * + * @since 1.1 */ -public boolean -isMultipleMode() -{ + public boolean isMultipleMode() + { return allowsMultipleSelections (); -} + } -/*************************************************************************/ - -/** + /** * Tests whether or not multi-select mode is enabled. * * @return <code>true</code> if multi-select mode is enabled, @@ -271,30 +240,26 @@ * @deprecated This method is deprecated in favor of * <code>isMultipleMode()</code>. */ -public boolean -allowsMultipleSelections() -{ + public boolean allowsMultipleSelections() + { return multipleMode; -} + } -/*************************************************************************/ - -/** + /** * This method enables or disables multiple selection mode for this * list. * * @param multipleMode <code>true</code> to enable multiple mode, * <code>false</code> otherwise. + * + * @since 1.1 */ -public void -setMultipleMode(boolean multipleMode) -{ + public void setMultipleMode(boolean multipleMode) + { setMultipleSelections (multipleMode); -} + } -/*************************************************************************/ - -/** + /** * This method enables or disables multiple selection mode for this * list. * @@ -303,32 +268,29 @@ * * @deprecated */ -public void -setMultipleSelections(boolean multipleMode) -{ + public void setMultipleSelections(boolean multipleMode) + { this.multipleMode = multipleMode; - ListPeer peer = (ListPeer) getPeer (); + ListPeer peer = (ListPeer) getPeer(); if (peer != null) - peer.setMultipleMode (multipleMode); -} + peer.setMultipleMode(multipleMode); -/*************************************************************************/ + } -/** + /** * Returns the minimum size of this component. * * @return The minimum size of this component. + * + * @since 1.1 */ -public Dimension -getMinimumSize() -{ - return getMinimumSize (getRows ()); -} + public Dimension getMinimumSize() + { + return getMinimumSize(getRows()); + } -/*************************************************************************/ - -/** + /** * Returns the minimum size of this component. * * @return The minimum size of this component. @@ -336,31 +298,27 @@ * @deprecated This method is deprecated in favor of * <code>getMinimumSize</code>. */ -public Dimension -minimumSize() -{ - return minimumSize (getRows ()); -} + public Dimension minimumSize() + { + return minimumSize(getRows()); + } -/*************************************************************************/ - -/** + /** * Returns the minimum size of this component assuming it had the specified * number of rows. * * @param rows The number of rows to size for. * * @return The minimum size of this component. + * + * @since 1.1 */ -public Dimension -getMinimumSize(int rows) -{ - return minimumSize (rows); -} + public Dimension getMinimumSize(int rows) + { + return minimumSize(rows); + } -/*************************************************************************/ - -/** + /** * Returns the minimum size of this component assuming it had the specified * number of rows. * @@ -371,32 +329,28 @@ * @deprecated This method is deprecated in favor of * <code>getMinimumSize(int)</code>> */ -public Dimension -minimumSize(int rows) -{ - ListPeer peer = (ListPeer) getPeer (); + public Dimension minimumSize(int rows) + { + ListPeer peer = (ListPeer) getPeer(); if (peer != null) - return peer.minimumSize (rows); + return peer.minimumSize(rows); else - return new Dimension (0, 0); -} + return new Dimension(0, 0); + } -/*************************************************************************/ - -/** + /** * Returns the preferred size of this component. * * @return The preferred size of this component. + * + * @since 1.1 */ -public Dimension -getPreferredSize() -{ - return getPreferredSize (getRows ()); -} + public Dimension getPreferredSize() + { + return getPreferredSize(getRows()); + } -/*************************************************************************/ - -/** + /** * Returns the preferred size of this component. * * @return The preferred size of this component. @@ -404,31 +358,27 @@ * @deprecated This method is deprecated in favor of * <code>getPreferredSize</code>. */ -public Dimension -preferredSize() -{ - return preferredSize (getRows ()); -} + public Dimension preferredSize() + { + return preferredSize(getRows()); + } -/*************************************************************************/ - -/** + /** * Returns the preferred size of this component assuming it had the specified * number of rows. * * @param rows The number of rows to size for. * * @return The preferred size of this component. + * + * @since 1.1 */ -public Dimension -getPreferredSize(int rows) -{ - return preferredSize (rows); -} + public Dimension getPreferredSize(int rows) + { + return preferredSize(rows); + } -/*************************************************************************/ - -/** + /** * Returns the preferred size of this component assuming it had the specified * number of rows. * @@ -439,47 +389,40 @@ * @deprecated This method is deprecated in favor of * <code>getPreferredSize(int)</code>> */ -public Dimension -preferredSize(int rows) -{ - ListPeer peer = (ListPeer) getPeer (); + public Dimension preferredSize(int rows) + { + ListPeer peer = (ListPeer)getPeer(); if (peer != null) - return peer.preferredSize (rows); + return peer.preferredSize(rows); else return getSize(); -} + } -/*************************************************************************/ - -/** + /** * This method adds the specified item to the end of the list. * * @param item The item to add to the list. + * + * @since 1.1 */ -public void -add(String item) -{ + public void add(String item) + { add (item, -1); -} + } -/*************************************************************************/ - -/** + /** * This method adds the specified item to the end of the list. * * @param item The item to add to the list. * * @deprecated Use add() instead. */ -public void -addItem(String item) -{ - addItem (item, -1); -} + public void addItem(String item) + { + addItem(item, -1); + } -/*************************************************************************/ - -/** + /** * Adds the specified item to the specified location in the list. * If the desired index is -1 or greater than the number of rows * in the list, then the item is added to the end. @@ -487,16 +430,15 @@ * @param item The item to add to the list. * @param index The location in the list to add the item, or -1 to add * to the end. + * + * @since 1.1 */ -public void -add(String item, int index) -{ - addItem (item, index); -} + public void add(String item, int index) + { + addItem(item, index); + } -/*************************************************************************/ - -/** + /** * Adds the specified item to the specified location in the list. * If the desired index is -1 or greater than the number of rows * in the list, then the item is added to the end. @@ -507,22 +449,25 @@ * * @deprecated Use add() instead. */ -public void -addItem(String item, int index) -{ + public void addItem(String item, int index) + { + if (item == null) + item = ""; + + if (index < -1) + index = -1; + if ((index == -1) || (index >= items.size ())) items.addElement (item); else - items.insertElementAt (item, index); + items.insertElementAt(item, index); - ListPeer peer = (ListPeer) getPeer (); + ListPeer peer = (ListPeer) getPeer(); if (peer != null) peer.add (item, index); -} + } -/*************************************************************************/ - -/** + /** * Deletes the item at the specified index. * * @param index The index of the item to delete. @@ -531,34 +476,40 @@ * * @deprecated */ -public void -delItem(int index) throws IllegalArgumentException -{ + public void delItem(int index) throws IllegalArgumentException + { + boolean selected = false; + if (isSelected(index)) + { + selected = true; + deselect(index); + } + items.removeElementAt (index); - ListPeer peer = (ListPeer) getPeer (); + if (selected) + select(index); + + ListPeer peer = (ListPeer) getPeer(); if (peer != null) peer.delItems (index, index); -} + } -/*************************************************************************/ - -/** + /** * Deletes the item at the specified index. * * @param index The index of the item to delete. * * @exception IllegalArgumentException If the index is not valid + * + * @since 1.1 */ -public void -remove(int index) throws IllegalArgumentException -{ - delItem (index); -} + public void remove(int index) throws IllegalArgumentException + { + delItem(index); + } -/*************************************************************************/ - -/** + /** * Deletes all items in the specified index range. * * @param start The beginning index of the range to delete. @@ -568,18 +519,9 @@ * * @deprecated This method is deprecated for some unknown reason. */ -public synchronized void -delItems(int start, int end) throws IllegalArgumentException -{ - if ((start < 0) || (start >= items.size())) - throw new IllegalArgumentException("Bad list start index value: " + start); - - if ((start < 0) || (start >= items.size())) - throw new IllegalArgumentException("Bad list start index value: " + start); - - if (start > end) - throw new IllegalArgumentException("Start is greater than end!"); - + public synchronized void delItems(int start, int end) + throws IllegalArgumentException + { // We must run the loop in reverse direction. for (int i = end; i >= start; --i) items.removeElementAt (i); @@ -588,70 +530,65 @@ ListPeer l = (ListPeer) peer; l.delItems (start, end); } -} + } -/*************************************************************************/ - -/** + /** * Deletes the first occurrence of the specified item from the list. * * @param item The item to delete. * * @exception IllegalArgumentException If the specified item does not exist. + * + * @since 1.1 */ -public synchronized void -remove(String item) throws IllegalArgumentException -{ + public synchronized void remove(String item) throws IllegalArgumentException + { int index = items.indexOf(item); if (index == -1) throw new IllegalArgumentException("List element to delete not found"); remove(index); -} + } -/*************************************************************************/ - -/** + /** * Deletes all of the items from the list. + * + * @since 1.1 */ -public synchronized void -removeAll() -{ - clear (); -} + public synchronized void removeAll() + { + clear(); + } -/*************************************************************************/ - -/** + /** * Deletes all of the items from the list. * * @deprecated This method is deprecated in favor of <code>removeAll()</code>. */ -public... [truncated message content] |
From: <ls...@us...> - 2007-01-28 21:36:50
|
Revision: 3097 http://jnode.svn.sourceforge.net/jnode/?rev=3097&view=rev Author: lsantha Date: 2007-01-28 13:36:49 -0800 (Sun, 28 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/awt/Button.java trunk/core/src/classpath/java/java/awt/Component.java trunk/core/src/classpath/java/java/awt/MenuBar.java Modified: trunk/core/src/classpath/java/java/awt/Button.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Button.java 2007-01-28 20:52:02 UTC (rev 3096) +++ trunk/core/src/classpath/java/java/awt/Button.java 2007-01-28 21:36:49 UTC (rev 3097) @@ -352,11 +352,11 @@ * * @since 1.3 */ - public EventListener[] getListeners(Class listenerType) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { if (listenerType == ActionListener.class) - return getActionListeners(); - return (EventListener[]) Array.newInstance(listenerType, 0); + return (T[]) getActionListeners(); + return (T[]) Array.newInstance(listenerType, 0); } /*************************************************************************/ Modified: trunk/core/src/classpath/java/java/awt/Component.java =================================================================== --- trunk/core/src/classpath/java/java/awt/Component.java 2007-01-28 20:52:02 UTC (rev 3096) +++ trunk/core/src/classpath/java/java/awt/Component.java 2007-01-28 21:36:49 UTC (rev 3097) @@ -2847,29 +2847,29 @@ * @see #getPropertyChangeListeners() * @since 1.3 */ - public EventListener[] getListeners(Class listenerType) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { if (listenerType == ComponentListener.class) - return getComponentListeners(); + return (T[]) getComponentListeners(); if (listenerType == FocusListener.class) - return getFocusListeners(); + return (T[]) getFocusListeners(); if (listenerType == HierarchyListener.class) - return getHierarchyListeners(); + return (T[]) getHierarchyListeners(); if (listenerType == HierarchyBoundsListener.class) - return getHierarchyBoundsListeners(); + return (T[]) getHierarchyBoundsListeners(); if (listenerType == KeyListener.class) - return getKeyListeners(); + return (T[]) getKeyListeners(); if (listenerType == MouseListener.class) - return getMouseListeners(); + return (T[]) getMouseListeners(); if (listenerType == MouseMotionListener.class) - return getMouseMotionListeners(); + return (T[]) getMouseMotionListeners(); if (listenerType == MouseWheelListener.class) - return getMouseWheelListeners(); + return (T[]) getMouseWheelListeners(); if (listenerType == InputMethodListener.class) - return getInputMethodListeners(); + return (T[]) getInputMethodListeners(); if (listenerType == PropertyChangeListener.class) - return getPropertyChangeListeners(); - return (EventListener[]) Array.newInstance(listenerType, 0); + return (T[]) getPropertyChangeListeners(); + return (T[]) Array.newInstance(listenerType, 0); } /** Modified: trunk/core/src/classpath/java/java/awt/MenuBar.java =================================================================== --- trunk/core/src/classpath/java/java/awt/MenuBar.java 2007-01-28 20:52:02 UTC (rev 3096) +++ trunk/core/src/classpath/java/java/awt/MenuBar.java 2007-01-28 21:36:49 UTC (rev 3097) @@ -272,7 +272,7 @@ * * @return a list of all shortcuts for the menus in this menu bar */ - public synchronized Enumeration shortcuts() + public synchronized Enumeration<MenuShortcut> shortcuts() { Vector shortcuts = new Vector(); Enumeration e = menus.elements(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-28 20:52:04
|
Revision: 3096 http://jnode.svn.sourceforge.net/jnode/?rev=3096&view=rev Author: lsantha Date: 2007-01-28 12:52:02 -0800 (Sun, 28 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/lang/reflect/Array.java Added Paths: ----------- trunk/core/src/classpath/vm/java/lang/reflect/VMArray.java Modified: trunk/core/src/classpath/java/java/lang/reflect/Array.java =================================================================== --- trunk/core/src/classpath/java/java/lang/reflect/Array.java 2007-01-27 21:52:45 UTC (rev 3095) +++ trunk/core/src/classpath/java/java/lang/reflect/Array.java 2007-01-28 20:52:02 UTC (rev 3096) @@ -35,19 +35,9 @@ obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ + package java.lang.reflect; -import org.jnode.vm.Vm; -import org.jnode.vm.memmgr.VmHeapManager; -import org.jnode.vm.classmgr.VmType; -import org.jnode.vm.classmgr.VmClassLoader; -import org.jnode.vm.classmgr.VmArrayClass; - -import gnu.java.security.action.InvokeAction; - -import java.security.AccessController; -import java.security.PrivilegedAction; - /** * Array holds static helper functions that allow you to create and * manipulate arrays by reflection. Operations know how to perform widening @@ -105,10 +95,10 @@ * @throws NegativeArraySizeException when length is less than 0 * @throws OutOfMemoryError if memory allocation fails */ - public static Object newInstance(Class componentType, int length) + public static Object newInstance(Class<?> componentType, int length) { - if (!componentType.isPrimitive()) - return createObjectArray(componentType, length); + if (! componentType.isPrimitive()) + return VMArray.createObjectArray(componentType, length); if (componentType == boolean.class) return new boolean[length]; if (componentType == byte.class) @@ -153,10 +143,10 @@ * than 0 * @throws OutOfMemoryError if memory allocation fails */ - public static Object newInstance(Class componentType, int[] dimensions) + public static Object newInstance(Class<?> componentType, int[] dimensions) { if (dimensions.length <= 0) - throw new IllegalArgumentException("Empty dimensions array."); + throw new IllegalArgumentException ("Empty dimensions array."); return createMultiArray(componentType, dimensions, dimensions.length - 1); } @@ -175,7 +165,7 @@ if (array instanceof boolean[]) return ((boolean[]) array).length; if (array instanceof byte[]) - return ((byte[]) array).length; + return ((byte[]) array). length; if (array instanceof char[]) return ((char[]) array).length; if (array instanceof short[]) @@ -654,7 +644,7 @@ Object toAdd = createMultiArray(type, dimensions, index - 1); Class thisType = toAdd.getClass(); Object[] retval - = (Object[]) createObjectArray(thisType, dimensions[index]); + = (Object[]) VMArray.createObjectArray(thisType, dimensions[index]); if (dimensions[index] > 0) retval[0] = toAdd; int i = dimensions[index]; @@ -663,49 +653,4 @@ return retval; } - - // LS - // @classpath-bugfix-22923 should be placed in VMArray - /** - * Dynamically create an array of objects. - * - * @param type guaranteed to be a valid object type - * @param dim the length of the array - * @return the new array - * @throws NegativeArraySizeException if dim is negative - * @throws OutOfMemoryError if memory allocation fails - */ - private static Object createObjectArray(final Class type, int dim) { - final VmType vmClass = (VmType) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return type.getVmClass(); - } - }); - - final String arrClsName = vmClass.getArrayClassName(); - final VmType arrCls; - try { - final VmClassLoader curLoader = vmClass.getLoader(); - arrCls = curLoader.loadClass(arrClsName, true); - //Screen.debug("an cls{"); - //Screen.debug(vmClass.getName()); - if (arrCls == null) { - throw new NoClassDefFoundError(arrClsName); - } - } catch (ClassNotFoundException ex) { - throw new NoClassDefFoundError(arrClsName); - } - - VmHeapManager hm = heapManager; - if (hm == null) { - heapManager = hm = Vm.getVm().getHeapManager(); - } - final Object result = hm.newArray((VmArrayClass) arrCls, dim); - - //Screen.debug("}"); - return result; - } - private static VmHeapManager heapManager; - // @classpath-bugfix-end } Added: trunk/core/src/classpath/vm/java/lang/reflect/VMArray.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/reflect/VMArray.java (rev 0) +++ trunk/core/src/classpath/vm/java/lang/reflect/VMArray.java 2007-01-28 20:52:02 UTC (rev 3096) @@ -0,0 +1,91 @@ +/* java.lang.reflect.VMArray - VM class for array manipulation by reflection. + Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +import gnu.classpath.Configuration; +import org.jnode.vm.classmgr.VmType; +import org.jnode.vm.classmgr.VmClassLoader; +import org.jnode.vm.classmgr.VmArrayClass; +import org.jnode.vm.Vm; +import java.security.AccessController; +import java.security.PrivilegedAction; + +class VMArray +{ + + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("javalangreflect"); + } + } + + /** + * Dynamically create an array of objects. + * + * @param type guaranteed to be a valid object type + * @param dim the length of the array + * @return the new array + * @throws NegativeArraySizeException if dim is negative + * @throws OutOfMemoryError if memory allocation fails + */ + static Object createObjectArray(final Class type, int dim) { + final VmType vmClass = AccessController.doPrivileged( + new PrivilegedAction<VmType>() { + public VmType run() { + return type.getVmClass(); + } + }); + + final String arrClsName = vmClass.getArrayClassName(); + final VmType arrCls; + try { + final VmClassLoader curLoader = vmClass.getLoader(); + arrCls = curLoader.loadClass(arrClsName, true); + if (arrCls == null) { + throw new NoClassDefFoundError(arrClsName); + } + } catch (ClassNotFoundException ex) { + throw new NoClassDefFoundError(arrClsName); + } + + return Vm.getHeapManager().newArray((VmArrayClass) arrCls, dim); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ls...@us...> - 2007-01-27 21:52:49
|
Revision: 3095 http://jnode.svn.sourceforge.net/jnode/?rev=3095&view=rev Author: lsantha Date: 2007-01-27 13:52:45 -0800 (Sat, 27 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/lang/Compiler.java trunk/core/src/classpath/java/java/lang/Math.java trunk/core/src/classpath/java/java/lang/SecurityManager.java trunk/core/src/classpath/java/java/lang/StrictMath.java trunk/core/src/classpath/java/java/lang/ThreadGroup.java trunk/core/src/classpath/vm/java/lang/Thread.java Added Paths: ----------- trunk/core/src/classpath/vm/java/lang/VMMath.java Modified: trunk/core/src/classpath/java/java/lang/Compiler.java =================================================================== --- trunk/core/src/classpath/java/java/lang/Compiler.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/java/java/lang/Compiler.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -74,7 +74,7 @@ * compilation failed, <code>true</code> if compilation succeeded * @throws NullPointerException if oneClass is null */ - public static boolean compileClass(Class oneClass) + public static boolean compileClass(Class<?> oneClass) { return VMCompiler.compileClass(oneClass); } Modified: trunk/core/src/classpath/java/java/lang/Math.java =================================================================== --- trunk/core/src/classpath/java/java/lang/Math.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/java/java/lang/Math.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -1,5 +1,5 @@ -/* java.lang.Math -- common mathematical functions, native allowed - Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. +/* java.lang.Math -- common mathematical functions, native allowed (VMMath) + Copyright (C) 1998, 2001, 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,6 +38,8 @@ package java.lang; +import gnu.classpath.Configuration; + import java.util.Random; /** @@ -50,10 +52,26 @@ * @author Paul Fisher * @author John Keiser * @author Eric Blake (eb...@em...) + * @author Andrew John Hughes (gnu...@me...) * @since 1.0 */ public final class Math { + + // FIXME - This is here because we need to load the "javalang" system + // library somewhere late in the bootstrap cycle. We cannot do this + // from VMSystem or VMRuntime since those are used to actually load + // the library. This is mainly here because historically Math was + // late enough in the bootstrap cycle to start using System after it + // was initialized (called from the java.util classes). + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("javalang"); + } + } + /** * Math is non-instantiable */ @@ -288,11 +306,10 @@ * @param a the angle (in radians) * @return sin(a) */ - // @classpath-bugfix-22918 - public static double sin(double a) { - return StrictMath.sin(a); + public static double sin(double a) + { + return VMMath.sin(a); } - // @classpath-bugfix-end /** * The trigonometric function <em>cos</em>. The cosine of NaN or infinity is @@ -301,11 +318,10 @@ * @param a the angle (in radians) * @return cos(a) */ - // @classpath-bugfix-22918 - public static double cos(double a) { - return StrictMath.cos(a); + public static double cos(double a) + { + return VMMath.cos(a); } - // @classpath-bugfix-end /** * The trigonometric function <em>tan</em>. The tangent of NaN or infinity @@ -315,11 +331,10 @@ * @param a the angle (in radians) * @return tan(a) */ - // @classpath-bugfix-22918 - public static double tan(double a) { - return StrictMath.tan(a); + public static double tan(double a) + { + return VMMath.tan(a); } - // @classpath-bugfix-end /** * The trigonometric function <em>arcsin</em>. The range of angles returned @@ -330,11 +345,10 @@ * @param a the sin to turn back into an angle * @return arcsin(a) */ - // @classpath-bugfix-22918 - public static double asin(double a) { - return StrictMath.asin(a); + public static double asin(double a) + { + return VMMath.asin(a); } - // @classpath-bugfix-end /** * The trigonometric function <em>arccos</em>. The range of angles returned @@ -345,11 +359,10 @@ * @param a the cos to turn back into an angle * @return arccos(a) */ - // @classpath-bugfix-22918 - public static double acos(double a) { - return StrictMath.acos(a); + public static double acos(double a) + { + return VMMath.acos(a); } - // @classpath-bugfix-end /** * The trigonometric function <em>arcsin</em>. The range of angles returned @@ -361,11 +374,10 @@ * @return arcsin(a) * @see #atan2(double, double) */ - // @classpath-bugfix-22918 - public static double atan(double a) { - return StrictMath.atan(a); + public static double atan(double a) + { + return VMMath.atan(a); } - // @classpath-bugfix-end /** * A special version of the trigonometric function <em>arctan</em>, for @@ -414,11 +426,10 @@ * @return <em>theta</em> in the conversion of (x, y) to (r, theta) * @see #atan(double) */ - // @classpath-bugfix-22918 - public static double atan2(double y, double x) { - return StrictMath.atan2(y, x); + public static double atan2(double y, double x) + { + return VMMath.atan2(y,x); } - // @classpath-bugfix-end /** * Take <em>e</em><sup>a</sup>. The opposite of <code>log()</code>. If the @@ -432,11 +443,10 @@ * @see #log(double) * @see #pow(double, double) */ - // @classpath-bugfix-22918 - public static double exp(double a) { - return StrictMath.exp(a); + public static double exp(double a) + { + return VMMath.exp(a); } - // @classpath-bugfix-end /** * Take ln(a) (the natural log). The opposite of <code>exp()</code>. If the @@ -452,11 +462,10 @@ * @return the natural log of <code>a</code> * @see #exp(double) */ - // @classpath-bugfix-22918 - public static double log(double a) { - return StrictMath.log(a); + public static double log(double a) + { + return VMMath.log(a); } - // @classpath-bugfix-end /** * Take a square root. If the argument is NaN or negative, the result is @@ -464,17 +473,18 @@ * infinity; and if the result is either zero, the result is the same. * This is accurate within the limits of doubles. * - * <p>For other roots, use pow(a, 1 / rootNumber). + * <p>For a cube root, use <code>cbrt</code>. For other roots, use + * <code>pow(a, 1 / rootNumber)</code>.</p> * * @param a the numeric argument * @return the square root of the argument + * @see #cbrt(double) * @see #pow(double, double) */ - // @classpath-bugfix-22918 - public static double sqrt(double a) { - return StrictMath.sqrt(a); + public static double sqrt(double a) + { + return VMMath.sqrt(a); } - // @classpath-bugfix-end /** * Raise a number to a power. Special cases:<ul> @@ -544,11 +554,10 @@ * @param b the power to raise it to * @return a<sup>b</sup> */ - // @classpath-bugfix-22918 - public static double pow(double a, double b) { - return StrictMath.pow(a, b); + public static double pow(double a, double b) + { + return VMMath.pow(a,b); } - // @classpath-bugfix-end /** * Get the IEEE 754 floating point remainder on two numbers. This is the @@ -564,11 +573,10 @@ * @return the IEEE 754-defined floating point remainder of x/y * @see #rint(double) */ - // @classpath-bugfix-22918 - public static double IEEEremainder(double x, double y) { - return StrictMath.IEEEremainder(x, y); + public static double IEEEremainder(double x, double y) + { + return VMMath.IEEEremainder(x,y); } - // @classpath-bugfix-end /** * Take the nearest integer that is that is greater than or equal to the @@ -579,11 +587,10 @@ * @param a the value to act upon * @return the nearest integer >= <code>a</code> */ - // @classpath-bugfix-22918 - public static double ceil(double a) { - return StrictMath.ceil(a); + public static double ceil(double a) + { + return VMMath.ceil(a); } - // @classpath-bugfix-end /** * Take the nearest integer that is that is less than or equal to the @@ -593,11 +600,10 @@ * @param a the value to act upon * @return the nearest integer <= <code>a</code> */ - // @classpath-bugfix-22918 - public static double floor(double a) { - return StrictMath.floor(a); + public static double floor(double a) + { + return VMMath.floor(a); } - // @classpath-bugfix-end /** * Take the nearest integer to the argument. If it is exactly between @@ -607,12 +613,10 @@ * @param a the value to act upon * @return the nearest integer to <code>a</code> */ - // @classpath-bugfix-22918 public static double rint(double a) { - return StrictMath.rint(a); + return VMMath.rint(a); } - // @classpath-bugfix-end /** * Take the nearest integer to the argument. This is equivalent to @@ -701,6 +705,99 @@ /** * <p> + * Take a cube root. If the argument is <code>NaN</code>, an infinity or + * zero, then the original value is returned. The returned result is + * within 1 ulp of the exact result. For a finite value, <code>x</code>, + * the cube root of <code>-x</code> is equal to the negation of the cube root + * of <code>x</code>. + * </p> + * <p> + * For a square root, use <code>sqrt</code>. For other roots, use + * <code>pow(a, 1 / rootNumber)</code>. + * </p> + * + * @param a the numeric argument + * @return the cube root of the argument + * @see #sqrt(double) + * @see #pow(double, double) + * @since 1.5 + */ + public static double cbrt(double a) + { + return VMMath.cbrt(a); + } + + /** + * <p> + * Returns the hyperbolic cosine of the given value. For a value, + * <code>x</code>, the hyperbolic cosine is <code>(e<sup>x</sup> + + * e<sup>-x</sup>)/2</code> + * with <code>e</code> being <a href="#E">Euler's number</a>. The returned + * result is within 2.5 ulps of the exact result. + * </p> + * <p> + * If the supplied value is <code>NaN</code>, then the original value is + * returned. For either infinity, positive infinity is returned. + * The hyperbolic cosine of zero is 1.0. + * </p> + * + * @param a the numeric argument + * @return the hyperbolic cosine of <code>a</code>. + * @since 1.5 + */ + public static double cosh(double a) + { + return VMMath.cosh(a); + } + + /** + * <p> + * Returns <code>e<sup>a</sup> - 1. For values close to 0, the + * result of <code>expm1(a) + 1</code> tend to be much closer to the + * exact result than simply <code>exp(x)</code>. The result is within + * 1 ulp of the exact result, and results are semi-monotonic. For finite + * inputs, the returned value is greater than or equal to -1.0. Once + * a result enters within half a ulp of this limit, the limit is returned. + * </p> + * <p> + * For <code>NaN</code>, positive infinity and zero, the original value + * is returned. Negative infinity returns a result of -1.0 (the limit). + * </p> + * + * @param a the numeric argument + * @return <code>e<sup>a</sup> - 1</code> + * @since 1.5 + */ + public static double expm1(double a) + { + return VMMath.expm1(a); + } + + /** + * <p> + * Returns the hypotenuse, <code>a<sup>2</sup> + b<sup>2</sup></code>, + * without intermediate overflow or underflow. The returned result is + * within 1 ulp of the exact result. If one parameter is held constant, + * then the result in the other parameter is semi-monotonic. + * </p> + * <p> + * If either of the arguments is an infinity, then the returned result + * is positive infinity. Otherwise, if either argument is <code>NaN</code>, + * then <code>NaN</code> is returned. + * </p> + * + * @param a the first parameter. + * @param b the second parameter. + * @return the hypotenuse matching the supplied parameters. + * @since 1.5 + */ + public static double hypot(double a, double b) + { + return VMMath.hypot(a,b); + } + + /** + * <p> * Returns the base 10 logarithm of the supplied value. The returned * result is within 1 ulp of the exact result, and the results are * semi-monotonic. @@ -719,7 +816,7 @@ */ public static double log10(double a) { - return log(a)/log(10); + return VMMath.log10(a); } /** @@ -744,7 +841,7 @@ */ public static double log1p(double a) { - return log(a + 1); + return VMMath.log1p(a); } /** @@ -800,7 +897,58 @@ return -1.0f; return a; } + /** + * <p> + * Returns the hyperbolic sine of the given value. For a value, + * <code>x</code>, the hyperbolic sine is <code>(e<sup>x</sup> - + * e<sup>-x</sup>)/2</code> + * with <code>e</code> being <a href="#E">Euler's number</a>. The returned + * result is within 2.5 ulps of the exact result. + * </p> + * <p> + * If the supplied value is <code>NaN</code>, an infinity or a zero, then the + * original value is returned. + * </p> + * + * @param a the numeric argument + * @return the hyperbolic sine of <code>a</code>. + * @since 1.5 + */ + public static double sinh(double a) + { + return VMMath.sinh(a); + } + + /** + * <p> + * Returns the hyperbolic tangent of the given value. For a value, + * <code>x</code>, the hyperbolic tangent is <code>(e<sup>x</sup> - + * e<sup>-x</sup>)/(e<sup>x</sup> + e<sup>-x</sup>)</code> + * (i.e. <code>sinh(a)/cosh(a)</code>) + * with <code>e</code> being <a href="#E">Euler's number</a>. The returned + * result is within 2.5 ulps of the exact result. The absolute value + * of the exact result is always less than 1. Computed results are thus + * less than or equal to 1 for finite arguments, with results within + * half a ulp of either positive or negative 1 returning the appropriate + * limit value (i.e. as if the argument was an infinity). + * </p> + * <p> + * If the supplied value is <code>NaN</code> or zero, then the original + * value is returned. Positive infinity returns +1.0 and negative infinity + * returns -1.0. + * </p> + * + * @param a the numeric argument + * @return the hyperbolic tangent of <code>a</code>. + * @since 1.5 + */ + public static double tanh(double a) + { + return VMMath.tanh(a); + } + + /** * Return the ulp for the given double argument. The ulp is the * difference between the argument and the next larger double. Note * that the sign of the double argument is ignored, that is, Modified: trunk/core/src/classpath/java/java/lang/SecurityManager.java =================================================================== --- trunk/core/src/classpath/java/java/lang/SecurityManager.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/java/java/lang/SecurityManager.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -1,5 +1,5 @@ /* SecurityManager.java -- security checks for privileged actions - Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -240,7 +240,7 @@ * @return the most recent non-system Class on the execution stack * @deprecated use {@link #checkPermission(Permission)} instead */ - protected Class currentLoadedClass() + protected Class<?> currentLoadedClass() { int i = classLoaderDepth(); return i >= 0 ? getClassContext()[i] : null; @@ -421,7 +421,7 @@ public void checkAccess(Thread thread) { if (thread.getThreadGroup() != null - && thread.getThreadGroup().getParent() == null) + && thread.getThreadGroup().parent == null) checkPermission(new RuntimePermission("modifyThread")); } @@ -454,7 +454,7 @@ */ public void checkAccess(ThreadGroup g) { - if (g.getParent() == null) + if (g.parent == null) checkPermission(new RuntimePermission("modifyThreadGroup")); } @@ -983,7 +983,7 @@ * @see Member#PUBLIC * @since 1.1 */ - public void checkMemberAccess(Class c, int memberType) + public void checkMemberAccess(Class<?> c, int memberType) { if (c == null) throw new NullPointerException(); Modified: trunk/core/src/classpath/java/java/lang/StrictMath.java =================================================================== --- trunk/core/src/classpath/java/java/lang/StrictMath.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/java/java/lang/StrictMath.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -1,5 +1,5 @@ /* java.lang.StrictMath -- common mathematical functions, strict Java - Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1998, 2001, 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -633,6 +633,381 @@ } /** + * Returns the hyperbolic sine of <code>x</code> which is defined as + * (exp(x) - exp(-x)) / 2. + * + * Special cases: + * <ul> + * <li>If the argument is NaN, the result is NaN</li> + * <li>If the argument is positive infinity, the result is positive + * infinity.</li> + * <li>If the argument is negative infinity, the result is negative + * infinity.</li> + * <li>If the argument is zero, the result is zero.</li> + * </ul> + * + * @param x the argument to <em>sinh</em> + * @return the hyperbolic sine of <code>x</code> + * + * @since 1.5 + */ + public static double sinh(double x) + { + // Method : + // mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2 + // 1. Replace x by |x| (sinh(-x) = -sinh(x)). + // 2. + // E + E/(E+1) + // 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x) + // 2 + // + // 22 <= x <= lnovft : sinh(x) := exp(x)/2 + // lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2) + // ln2ovft < x : sinh(x) := +inf (overflow) + + double t, w, h; + + long bits; + long h_bits; + long l_bits; + + // handle special cases + if (x != x) + return x; + if (x == Double.POSITIVE_INFINITY) + return Double.POSITIVE_INFINITY; + if (x == Double.NEGATIVE_INFINITY) + return Double.NEGATIVE_INFINITY; + + if (x < 0) + h = - 0.5; + else + h = 0.5; + + bits = Double.doubleToLongBits(x); + h_bits = getHighDWord(bits) & 0x7fffffffL; // ignore sign + l_bits = getLowDWord(bits); + + // |x| in [0, 22], return sign(x) * 0.5 * (E+E/(E+1)) + if (h_bits < 0x40360000L) // |x| < 22 + { + if (h_bits < 0x3e300000L) // |x| < 2^-28 + return x; // for tiny arguments return x + + t = expm1(abs(x)); + + if (h_bits < 0x3ff00000L) + return h * (2.0 * t - t * t / (t + 1.0)); + + return h * (t + t / (t + 1.0)); + } + + // |x| in [22, log(Double.MAX_VALUE)], return 0.5 * exp(|x|) + if (h_bits < 0x40862e42L) + return h * exp(abs(x)); + + // |x| in [log(Double.MAX_VALUE), overflowthreshold] + if ((h_bits < 0x408633ceL) + || ((h_bits == 0x408633ceL) && (l_bits <= 0x8fb9f87dL))) + { + w = exp(0.5 * abs(x)); + t = h * w; + + return t * w; + } + + // |x| > overflowthershold + return h * Double.POSITIVE_INFINITY; + } + + /** + * Returns the hyperbolic cosine of <code>x</code>, which is defined as + * (exp(x) + exp(-x)) / 2. + * + * Special cases: + * <ul> + * <li>If the argument is NaN, the result is NaN</li> + * <li>If the argument is positive infinity, the result is positive + * infinity.</li> + * <li>If the argument is negative infinity, the result is positive + * infinity.</li> + * <li>If the argument is zero, the result is one.</li> + * </ul> + * + * @param x the argument to <em>cosh</em> + * @return the hyperbolic cosine of <code>x</code> + * + * @since 1.5 + */ + public static double cosh(double x) + { + // Method : + // mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2 + // 1. Replace x by |x| (cosh(x) = cosh(-x)). + // 2. + // [ exp(x) - 1 ]^2 + // 0 <= x <= ln2/2 : cosh(x) := 1 + ------------------- + // 2*exp(x) + // + // exp(x) + 1/exp(x) + // ln2/2 <= x <= 22 : cosh(x) := ------------------ + // 2 + // 22 <= x <= lnovft : cosh(x) := exp(x)/2 + // lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2) + // ln2ovft < x : cosh(x) := +inf (overflow) + + double t, w; + long bits; + long hx; + long lx; + + // handle special cases + if (x != x) + return x; + if (x == Double.POSITIVE_INFINITY) + return Double.POSITIVE_INFINITY; + if (x == Double.NEGATIVE_INFINITY) + return Double.POSITIVE_INFINITY; + + bits = Double.doubleToLongBits(x); + hx = getHighDWord(bits) & 0x7fffffffL; // ignore sign + lx = getLowDWord(bits); + + // |x| in [0, 0.5 * ln(2)], return 1 + expm1(|x|)^2 / (2 * exp(|x|)) + if (hx < 0x3fd62e43L) + { + t = expm1(abs(x)); + w = 1.0 + t; + + // for tiny arguments return 1. + if (hx < 0x3c800000L) + return w; + + return 1.0 + (t * t) / (w + w); + } + + // |x| in [0.5 * ln(2), 22], return exp(|x|)/2 + 1 / (2 * exp(|x|)) + if (hx < 0x40360000L) + { + t = exp(abs(x)); + + return 0.5 * t + 0.5 / t; + } + + // |x| in [22, log(Double.MAX_VALUE)], return 0.5 * exp(|x|) + if (hx < 0x40862e42L) + return 0.5 * exp(abs(x)); + + // |x| in [log(Double.MAX_VALUE), overflowthreshold], + // return exp(x/2)/2 * exp(x/2) + if ((hx < 0x408633ceL) + || ((hx == 0x408633ceL) && (lx <= 0x8fb9f87dL))) + { + w = exp(0.5 * abs(x)); + t = 0.5 * w; + + return t * w; + } + + // |x| > overflowthreshold + return Double.POSITIVE_INFINITY; + } + + /** + * Returns the hyperbolic tangent of <code>x</code>, which is defined as + * (exp(x) - exp(-x)) / (exp(x) + exp(-x)), i.e. sinh(x) / cosh(x). + * + Special cases: + * <ul> + * <li>If the argument is NaN, the result is NaN</li> + * <li>If the argument is positive infinity, the result is 1.</li> + * <li>If the argument is negative infinity, the result is -1.</li> + * <li>If the argument is zero, the result is zero.</li> + * </ul> + * + * @param x the argument to <em>tanh</em> + * @return the hyperbolic tagent of <code>x</code> + * + * @since 1.5 + */ + public static double tanh(double x) + { + // Method : + // 0. tanh(x) is defined to be (exp(x) - exp(-x)) / (exp(x) + exp(-x)) + // 1. reduce x to non-negative by tanh(-x) = -tanh(x). + // 2. 0 <= x <= 2^-55 : tanh(x) := x * (1.0 + x) + // -t + // 2^-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x) + // t + 2 + // 2 + // 1 <= x <= 22.0 : tanh(x) := 1 - ----- ; t=expm1(2x) + // t + 2 + // 22.0 < x <= INF : tanh(x) := 1. + + double t, z; + + long bits; + long h_bits; + + // handle special cases + if (x != x) + return x; + if (x == Double.POSITIVE_INFINITY) + return 1.0; + if (x == Double.NEGATIVE_INFINITY) + return -1.0; + + bits = Double.doubleToLongBits(x); + h_bits = getHighDWord(bits) & 0x7fffffffL; // ingnore sign + + if (h_bits < 0x40360000L) // |x| < 22 + { + if (h_bits < 0x3c800000L) // |x| < 2^-55 + return x * (1.0 + x); + + if (h_bits >= 0x3ff00000L) // |x| >= 1 + { + t = expm1(2.0 * abs(x)); + z = 1.0 - 2.0 / (t + 2.0); + } + else // |x| < 1 + { + t = expm1(-2.0 * abs(x)); + z = -t / (t + 2.0); + } + } + else // |x| >= 22 + z = 1.0; + + return (x >= 0) ? z : -z; + } + + /** + * Returns the lower two words of a long. This is intended to be + * used like this: + * <code>getLowDWord(Double.doubleToLongBits(x))</code>. + */ + private static long getLowDWord(long x) + { + return x & 0x00000000ffffffffL; + } + + /** + * Returns the higher two words of a long. This is intended to be + * used like this: + * <code>getHighDWord(Double.doubleToLongBits(x))</code>. + */ + private static long getHighDWord(long x) + { + return (x & 0xffffffff00000000L) >> 32; + } + + /** + * Returns a double with the IEEE754 bit pattern given in the lower + * and higher two words <code>lowDWord</code> and <code>highDWord</code>. + */ + private static double buildDouble(long lowDWord, long highDWord) + { + return Double.longBitsToDouble(((highDWord & 0xffffffffL) << 32) + | (lowDWord & 0xffffffffL)); + } + + /** + * Returns the cube root of <code>x</code>. The sign of the cube root + * is equal to the sign of <code>x</code>. + * + * Special cases: + * <ul> + * <li>If the argument is NaN, the result is NaN</li> + * <li>If the argument is positive infinity, the result is positive + * infinity.</li> + * <li>If the argument is negative infinity, the result is negative + * infinity.</li> + * <li>If the argument is zero, the result is zero with the same + * sign as the argument.</li> + * </ul> + * + * @param x the number to take the cube root of + * @return the cube root of <code>x</code> + * @see #sqrt(double) + * + * @since 1.5 + */ + public static double cbrt(double x) + { + boolean negative = (x < 0); + double r; + double s; + double t; + double w; + + long bits; + long l; + long h; + + // handle the special cases + if (x != x) + return x; + if (x == Double.POSITIVE_INFINITY) + return Double.POSITIVE_INFINITY; + if (x == Double.NEGATIVE_INFINITY) + return Double.NEGATIVE_INFINITY; + if (x == 0) + return x; + + x = abs(x); + bits = Double.doubleToLongBits(x); + + if (bits < 0x0010000000000000L) // subnormal number + { + t = TWO_54; + t *= x; + + // __HI(t)=__HI(t)/3+B2; + bits = Double.doubleToLongBits(t); + h = getHighDWord(bits); + l = getLowDWord(bits); + + h = h / 3 + CBRT_B2; + + t = buildDouble(l, h); + } + else + { + // __HI(t)=__HI(x)/3+B1; + h = getHighDWord(bits); + l = 0; + + h = h / 3 + CBRT_B1; + t = buildDouble(l, h); + } + + // new cbrt to 23 bits + r = t * t / x; + s = CBRT_C + r * t; + t *= CBRT_G + CBRT_F / (s + CBRT_E + CBRT_D / s); + + // chopped to 20 bits and make it larger than cbrt(x) + bits = Double.doubleToLongBits(t); + h = getHighDWord(bits); + + // __LO(t)=0; + // __HI(t)+=0x00000001; + l = 0; + h += 1; + t = buildDouble(l, h); + + // one step newton iteration to 53 bits with error less than 0.667 ulps + s = t * t; // t * t is exact + r = x / s; + w = t + t; + r = (r - t) / (w + r); // r - t is exact + t = t + t * r; + + return negative ? -t : t; + } + + /** * Take <em>e</em><sup>a</sup>. The opposite of <code>log()</code>. If the * argument is NaN, the result is NaN; if the argument is positive infinity, * the result is positive infinity; and if the argument is negative @@ -694,6 +1069,254 @@ } /** + * Returns <em>e</em><sup>x</sup> - 1. + * Special cases: + * <ul> + * <li>If the argument is NaN, the result is NaN.</li> + * <li>If the argument is positive infinity, the result is positive + * infinity</li> + * <li>If the argument is negative infinity, the result is -1.</li> + * <li>If the argument is zero, the result is zero.</li> + * </ul> + * + * @param x the argument to <em>e</em><sup>x</sup> - 1. + * @return <em>e</em> raised to the power <code>x</code> minus one. + * @see #exp(double) + */ + public static double expm1(double x) + { + // Method + // 1. Argument reduction: + // Given x, find r and integer k such that + // + // x = k * ln(2) + r, |r| <= 0.5 * ln(2) + // + // Here a correction term c will be computed to compensate + // the error in r when rounded to a floating-point number. + // + // 2. Approximating expm1(r) by a special rational function on + // the interval [0, 0.5 * ln(2)]: + // Since + // r*(exp(r)+1)/(exp(r)-1) = 2 + r^2/6 - r^4/360 + ... + // we define R1(r*r) by + // r*(exp(r)+1)/(exp(r)-1) = 2 + r^2/6 * R1(r*r) + // That is, + // R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) + // = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) + // = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... + // We use a special Remes algorithm on [0, 0.347] to generate + // a polynomial of degree 5 in r*r to approximate R1. The + // maximum error of this polynomial approximation is bounded + // by 2**-61. In other words, + // R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 + // where Q1 = -1.6666666666666567384E-2, + // Q2 = 3.9682539681370365873E-4, + // Q3 = -9.9206344733435987357E-6, + // Q4 = 2.5051361420808517002E-7, + // Q5 = -6.2843505682382617102E-9; + // (where z=r*r, and Q1 to Q5 are called EXPM1_Qx in the source) + // with error bounded by + // | 5 | -61 + // | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 + // | | + // + // expm1(r) = exp(r)-1 is then computed by the following + // specific way which minimize the accumulation rounding error: + // 2 3 + // r r [ 3 - (R1 + R1*r/2) ] + // expm1(r) = r + --- + --- * [--------------------] + // 2 2 [ 6 - r*(3 - R1*r/2) ] + // + // To compensate the error in the argument reduction, we use + // expm1(r+c) = expm1(r) + c + expm1(r)*c + // ~ expm1(r) + c + r*c + // Thus c+r*c will be added in as the correction terms for + // expm1(r+c). Now rearrange the term to avoid optimization + // screw up: + // ( 2 2 ) + // ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) + // expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) + // ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) + // ( ) + // + // = r - E + // 3. Scale back to obtain expm1(x): + // From step 1, we have + // expm1(x) = either 2^k*[expm1(r)+1] - 1 + // = or 2^k*[expm1(r) + (1-2^-k)] + // 4. Implementation notes: + // (A). To save one multiplication, we scale the coefficient Qi + // to Qi*2^i, and replace z by (x^2)/2. + // (B). To achieve maximum accuracy, we compute expm1(x) by + // (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) + // (ii) if k=0, return r-E + // (iii) if k=-1, return 0.5*(r-E)-0.5 + // (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) + // else return 1.0+2.0*(r-E); + // (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) + // (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else + // (vii) return 2^k(1-((E+2^-k)-r)) + + boolean negative = (x < 0); + double y, hi, lo, c, t, e, hxs, hfx, r1; + int k; + + long bits; + long h_bits; + long l_bits; + + c = 0.0; + y = abs(x); + + bits = Double.doubleToLongBits(y); + h_bits = getHighDWord(bits); + l_bits = getLowDWord(bits); + + // handle special cases and large arguments + if (h_bits >= 0x4043687aL) // if |x| >= 56 * ln(2) + { + if (h_bits >= 0x40862e42L) // if |x| >= EXP_LIMIT_H + { + if (h_bits >= 0x7ff00000L) + { + if (((h_bits & 0x000fffffL) | (l_bits & 0xffffffffL)) != 0) + return x; // exp(NaN) = NaN + else + return negative ? -1.0 : x; // exp({+-inf}) = {+inf, -1} + } + + if (x > EXP_LIMIT_H) + return Double.POSITIVE_INFINITY; // overflow + } + + if (negative) // x <= -56 * ln(2) + return -1.0; + } + + // argument reduction + if (h_bits > 0x3fd62e42L) // |x| > 0.5 * ln(2) + { + if (h_bits < 0x3ff0a2b2L) // |x| < 1.5 * ln(2) + { + if (negative) + { + hi = x + LN2_H; + lo = -LN2_L; + k = -1; + } + else + { + hi = x - LN2_H; + lo = LN2_L; + k = 1; + } + } + else + { + k = (int) (INV_LN2 * x + (negative ? - 0.5 : 0.5)); + t = k; + hi = x - t * LN2_H; + lo = t * LN2_L; + } + + x = hi - lo; + c = (hi - x) - lo; + + } + else if (h_bits < 0x3c900000L) // |x| < 2^-54 return x + return x; + else + k = 0; + + // x is now in primary range + hfx = 0.5 * x; + hxs = x * hfx; + r1 = 1.0 + hxs * (EXPM1_Q1 + + hxs * (EXPM1_Q2 + + hxs * (EXPM1_Q3 + + hxs * (EXPM1_Q4 + + hxs * EXPM1_Q5)))); + t = 3.0 - r1 * hfx; + e = hxs * ((r1 - t) / (6.0 - x * t)); + + if (k == 0) + { + return x - (x * e - hxs); // c == 0 + } + else + { + e = x * (e - c) - c; + e -= hxs; + + if (k == -1) + return 0.5 * (x - e) - 0.5; + + if (k == 1) + { + if (x < - 0.25) + return -2.0 * (e - (x + 0.5)); + else + return 1.0 + 2.0 * (x - e); + } + + if (k <= -2 || k > 56) // sufficient to return exp(x) - 1 + { + y = 1.0 - (e - x); + + bits = Double.doubleToLongBits(y); + h_bits = getHighDWord(bits); + l_bits = getLowDWord(bits); + + h_bits += (k << 20); // add k to y's exponent + + y = buildDouble(l_bits, h_bits); + + return y - 1.0; + } + + t = 1.0; + if (k < 20) + { + bits = Double.doubleToLongBits(t); + h_bits = 0x3ff00000L - (0x00200000L >> k); + l_bits = getLowDWord(bits); + + t = buildDouble(l_bits, h_bits); // t = 1 - 2^(-k) + y = t - (e - x); + + bits = Double.doubleToLongBits(y); + h_bits = getHighDWord(bits); + l_bits = getLowDWord(bits); + + h_bits += (k << 20); // add k to y's exponent + + y = buildDouble(l_bits, h_bits); + } + else + { + bits = Double.doubleToLongBits(t); + h_bits = (0x000003ffL - k) << 20; + l_bits = getLowDWord(bits); + + t = buildDouble(l_bits, h_bits); // t = 2^(-k) + + y = x - (e + t); + y += 1.0; + + bits = Double.doubleToLongBits(y); + h_bits = getHighDWord(bits); + l_bits = getLowDWord(bits); + + h_bits += (k << 20); // add k to y's exponent + + y = buildDouble(l_bits, h_bits); + } + } + + return y; + } + + /** * Take ln(a) (the natural log). The opposite of <code>exp()</code>. If the * argument is NaN or negative, the result is NaN; if the argument is * positive infinity, the result is positive infinity; and if the argument @@ -1429,6 +2052,33 @@ AT10 = 0.016285820115365782; // Long bits 0x3f90ad3ae322da11L. /** + * Constants for computing {@link #cbrt(double)}. + */ + private static final int + CBRT_B1 = 715094163, // B1 = (682-0.03306235651)*2**20 + CBRT_B2 = 696219795; // B2 = (664-0.03306235651)*2**20 + + /** + * Constants for computing {@link #cbrt(double)}. + */ + private static final double + CBRT_C = 5.42857142857142815906e-01, // Long bits 0x3fe15f15f15f15f1L + CBRT_D = -7.05306122448979611050e-01, // Long bits 0xbfe691de2532c834L + CBRT_E = 1.41428571428571436819e+00, // Long bits 0x3ff6a0ea0ea0ea0fL + CBRT_F = 1.60714285714285720630e+00, // Long bits 0x3ff9b6db6db6db6eL + CBRT_G = 3.57142857142857150787e-01; // Long bits 0x3fd6db6db6db6db7L + + /** + * Constants for computing {@link #expm1(double)} + */ + private static final double + EXPM1_Q1 = -3.33333333333331316428e-02, // Long bits 0xbfa11111111110f4L + EXPM1_Q2 = 1.58730158725481460165e-03, // Long bits 0x3f5a01a019fe5585L + EXPM1_Q3 = -7.93650757867487942473e-05, // Long bits 0xbf14ce199eaadbb7L + EXPM1_Q4 = 4.00821782732936239552e-06, // Long bits 0x3ed0cfca86e65239L + EXPM1_Q5 = -2.01099218183624371326e-07; // Long bits 0xbe8afdb76e09c32dL + + /** * Helper function for reducing an angle to a multiple of pi/2 within * [-pi/4, pi/4]. * @@ -1628,8 +2278,9 @@ j |= iq[i]; if (j == 0) // Need recomputation. { - int k; - for (k = 1; iq[jk - k] == 0; k++); // k = no. of terms needed. + int k; // k = no. of terms needed. + for (k = 1; iq[jk - k] == 0; k++) + ; for (i = jz + 1; i <= jz + k; i++) // Add q[jz+1] to q[jz+k]. { @@ -1841,4 +2492,84 @@ double t = (float) a; return t + a * (1 + t * z + t * v); } + + /** + * <p> + * Returns the sign of the argument as follows: + * </p> + * <ul> + * <li>If <code>a</code> is greater than zero, the result is 1.0.</li> + * <li>If <code>a</code> is less than zero, the result is -1.0.</li> + * <li>If <code>a</code> is <code>NaN</code>, the result is <code>NaN</code>. + * <li>If <code>a</code> is positive or negative zero, the result is the + * same.</li> + * </ul> + * + * @param a the numeric argument. + * @return the sign of the argument. + * @since 1.5. + */ + public static double signum(double a) + { + // There's no difference. + return Math.signum(a); } + + /** + * <p> + * Returns the sign of the argument as follows: + * </p> + * <ul> + * <li>If <code>a</code> is greater than zero, the result is 1.0f.</li> + * <li>If <code>a</code> is less than zero, the result is -1.0f.</li> + * <li>If <code>a</code> is <code>NaN</code>, the result is <code>NaN</code>. + * <li>If <code>a</code> is positive or negative zero, the result is the + * same.</li> + * </ul> + * + * @param a the numeric argument. + * @return the sign of the argument. + * @since 1.5. + */ + public static float signum(float a) + { + // There's no difference. + return Math.signum(a); + } + + /** + * Return the ulp for the given double argument. The ulp is the + * difference between the argument and the next larger double. Note + * that the sign of the double argument is ignored, that is, + * ulp(x) == ulp(-x). If the argument is a NaN, then NaN is returned. + * If the argument is an infinity, then +Inf is returned. If the + * argument is zero (either positive or negative), then + * {@link Double#MIN_VALUE} is returned. + * @param d the double whose ulp should be returned + * @return the difference between the argument and the next larger double + * @since 1.5 + */ + public static double ulp(double d) + { + // There's no difference. + return Math.ulp(d); + } + + /** + * Return the ulp for the given float argument. The ulp is the + * difference between the argument and the next larger float. Note + * that the sign of the float argument is ignored, that is, + * ulp(x) == ulp(-x). If the argument is a NaN, then NaN is returned. + * If the argument is an infinity, then +Inf is returned. If the + * argument is zero (either positive or negative), then + * {@link Float#MIN_VALUE} is returned. + * @param f the float whose ulp should be returned + * @return the difference between the argument and the next larger float + * @since 1.5 + */ + public static float ulp(float f) + { + // There's no difference. + return Math.ulp(f); + } +} Modified: trunk/core/src/classpath/java/java/lang/ThreadGroup.java =================================================================== --- trunk/core/src/classpath/java/java/lang/ThreadGroup.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/java/java/lang/ThreadGroup.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -37,6 +37,7 @@ package java.lang; +import java.lang.Thread.UncaughtExceptionHandler; import java.util.Vector; /** @@ -53,7 +54,7 @@ * @since 1.0 * @status updated to 1.4 */ -public class ThreadGroup +public class ThreadGroup implements UncaughtExceptionHandler { /** The Initial, top-level ThreadGroup. */ static ThreadGroup root = new ThreadGroup(); @@ -65,7 +66,7 @@ static boolean had_uncaught_exception; /** The parent thread group. */ - private final ThreadGroup parent; + final ThreadGroup parent; /** The group name, non-null. */ final String name; @@ -545,6 +546,8 @@ { if (parent != null) parent.uncaughtException(thread, t); + else if (Thread.getDefaultUncaughtExceptionHandler() != null) + Thread.getDefaultUncaughtExceptionHandler().uncaughtException(thread, t); else if (! (t instanceof ThreadDeath)) { if (t == null) @@ -746,4 +749,43 @@ parent.removeGroup(this); } } + + /* + * Helper method for the VM. Find a Thread by its Id. + * + * @param id The Thread Id. + * @return Thread object or null if thread doesn't exist. + */ + static Thread getThreadFromId(long id) + { + return root.getThreadFromIdImpl(id); + } + + private Thread getThreadFromIdImpl(long id) + { + synchronized (threads) + { + for (int i = 0; i < threads.size(); i++) + { + Thread t = (Thread) threads.get(i); + if (t.getId() == id) + return t; + } + } + Vector groups = this.groups; + if (groups != null) + { + synchronized (groups) + { + for (int i = 0; i < groups.size(); i++) + { + ThreadGroup g = (ThreadGroup) groups.get(i); + Thread t = g.getThreadFromIdImpl(id); + if (t != null) + return t; + } + } + } + return null; + } } // class ThreadGroup Modified: trunk/core/src/classpath/vm/java/lang/Thread.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/Thread.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/vm/java/lang/Thread.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -1,21 +1,41 @@ /* Thread -- an independent thread of executable code Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; If not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ + Free Software Foundation +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + package java.lang; import java.util.Map; @@ -32,205 +52,270 @@ import org.jnode.vm.scheduler.VmProcessor; import org.jnode.vm.scheduler.VmThread; + +/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 + * "The Java Language Specification", ISBN 0-201-63451-1 + * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. + * Status: Believed complete to version 1.4, with caveats. We do not + * implement the deprecated (and dangerous) stop, suspend, and resume + * methods. Security implementation is not complete. + */ + /** - * Kore implementation of the <code>java.lang.Thread</code> class. - * <p> - * All native methods are indirected through <code>java.lang.NativeLang</code>. - * - * @version Kore 0.0.3, June 1997 - * @author Glynn Clements <a href="mailto:gl...@se...">gl...@se... - * </a> - * @author E. Prangsma (connection to JNode) + * Thread represents a single thread of execution in the VM. When an + * application VM starts up, it creates a non-daemon Thread which calls the + * main() method of a particular class. There may be other Threads running, + * such as the garbage collection thread. + * + * <p>Threads have names to identify them. These names are not necessarily + * unique. Every Thread has a priority, as well, which tells the VM which + * Threads should get more running time. New threads inherit the priority + * and daemon status of the parent thread, by default. + * + * <p>There are two methods of creating a Thread: you may subclass Thread and + * implement the <code>run()</code> method, at which point you may start the + * Thread by calling its <code>start()</code> method, or you may implement + * <code>Runnable</code> in the class you want to use and then call new + * <code>Thread(your_obj).start()</code>. + * + * <p>The virtual machine runs until all non-daemon threads have died (either + * by returning from the run() method as invoked by start(), or by throwing + * an uncaught exception); or until <code>System.exit</code> is called with + * adequate permissions. + * + * <p>It is unclear at what point a Thread should be added to a ThreadGroup, + * and at what point it should be removed. Should it be inserted when it + * starts, or when it is created? Should it be removed when it is suspended + * or interrupted? The only thing that is clear is that the Thread should be + * removed when it is stopped. + * + * @author Tom Tromey + * @author John Keiser + * @author Eric Blake (eb...@em...) + * @author Andrew John Hughes (gnu...@me...) + * @see Runnable + * @see Runtime#exit(int) + * @see #run() + * @see #start() + * @see ThreadLocal + * @since 1.0 + * @status updated to 1.4 */ -public class Thread implements Runnable { +public class Thread implements Runnable +{ + /** The minimum priority for a Thread. */ + public static final int MIN_PRIORITY = 1; - /** - * Number of threads created. Used only for generating "unique" names. - * - * @see java.lang.Thread#autoName() + /** The priority a Thread gets by default. */ + public static final int NORM_PRIORITY = 5; + + /** The maximum priority for a Thread. */ + public static final int MAX_PRIORITY = 10; + + /** The VM thread implementing this thread */ + private final VmThread vmThread; + + /** The group this thread belongs to. + * */ - private static int count = 0; + ThreadGroup group; - private static final JNodePermission GETVMTHREAD_PERM = new JNodePermission( - "getVmThread"); + /** The object to run(), null if this is the target. */ + final Runnable runnable; - public final static int MAX_PRIORITY = 10; + /** The name of this thread */ + String name; - public final static int MIN_PRIORITY = 1; + /** Is this a daemon thread? */ + private boolean daemon; - public final static int NORM_PRIORITY = 5; + /** The context classloader of this thread */ + private ClassLoader contextClassLoader; + /** The thread in which I was created */ + private final Thread parent; + + /** The default exception handler. */ + private static UncaughtExceptionHandler defaultHandler; + /** Thread local storage. Package accessible for use by * InheritableThreadLocal. */ WeakHashMap locals; - /** - * Gets the active number of threads in the current thread's thread group. - * - * @return the active number of threads in the current thread's thread - * group. - */ - public static int activeCount() { - return currentThread().getThreadGroup().activeCount(); - } + /** The uncaught exception handler. */ + UncaughtExceptionHandler exceptionHandler; /** - * Generate a "unique" default name for a thread. + * Number of threads created. Used only for generating "unique" names. + * + * @see java.lang.Thread#autoName() */ - private static synchronized String autoName() { - return "Thread-" + (++count); - } + private static int count = 0; - /** - * Gets the current thread. - * - * @return - */ - public static Thread currentThread() { - VmThread current = VmThread.currentThread(); - if (current != null) { - return current.asThread(); - } else { - return null; - } - } + private static final JNodePermission GETVMTHREAD_PERM = new JNodePermission( + "getVmThread"); /** - * Prints a stack trace of the current thread. - */ - public static void dumpStack() { - new Exception("Stack trace").printStackTrace(); + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, null,</code> + * <i>gname</i><code>)</code>, where <b><i>gname</i></b> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. + * <p> + * Threads created this way must have overridden their + * <code>run()</code> method to actually do anything. An example + * illustrating this method being used follows: + * <p><blockquote><pre> + * import java.lang.*; + * + * class plain01 implements Runnable { + * String name; + * plain01() { + * name = null; + * } + * plain01(String s) { + * name = s; + * } + * public void run() { + * if (name == null) + * System.out.println("A new thread created"); + * else + * System.out.println("A new thread with name " + name + + * " created"); + * } + * } + * class threadtest01 { + * public static void main(String args[] ) { + * int failed = 0 ; + * + * <b>Thread t1 = new Thread();</b> + * if (t1 != null) + * System.out.println("new Thread() succeed"); + * else { + * System.out.println("new Thread() failed"); + * failed++; + * } + * } + * } + * </pre></blockquote> + * + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) + */ + public Thread() + { + this(null, null, autoName()); } - public static int enumerate(Thread[] threads) { - return currentThread().getThreadGroup().enumerate(threads); - } - /** - * Checks whether the current thread holds the monitor on a given object. - * This allows you to do <code>assert Thread.holdsLock(obj)</code>. + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, target,</code> + * <i>gname</i><code>)</code>, where <i>gname</i> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. * - * @param obj - * the object to test lock ownership on. - * @return true if the current thread is currently synchronized on obj - * @throws NullPointerException - * if obj is null - * @since 1.4 + * @param target the object whose <code>run</code> method is called. + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) */ - public static boolean holdsLock(Object obj) { - return MonitorManager.holdsLock(obj); + public Thread(Runnable target) + { + this(null, target, autoName()); } /** - * Has the current thread been interrupted. - * The interrupted flag is cleared. - * @return + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, null, name)</code>. + * + * @param name the name of the new thread. + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) */ - public static boolean interrupted() { - VmThread current = VmThread.currentThread(); - if (current != null) { - return current.isInterrupted(true); - } else { - return false; - } + public Thread(String name) + { + this(null, null, name); } - public static void sleep(long millis) throws InterruptedException { - sleep(millis, 0); - } - /** - * XXX needs to be synchronized to avoid losing interrupts? it checks and - * sets state, which should be protected... + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(group, target,</code> + * <i>gname</i><code>)</code>, where <i>gname</i> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. + * + * @param group the group to put the Thread into + * @param target the Runnable object to execute + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see #Thread(ThreadGroup, Runnable, String) */ - public static void sleep(long millis, int nanos) - throws InterruptedException { - VmThread.currentThread().sleep(millis, nanos); + public Thread(ThreadGroup group, Runnable target) + { + this(group, target, autoName()); } - public static void yield() { - VmThread.yield(); - } - - /** The context classloader of this thread */ - private ClassLoader contextClassLoader; - - /** Is this a daemon thread? */ - private boolean daemon; - - /** The group this thread belongs to */ - ThreadGroup group; - - /** The name of this thread */ - String name; - - /** The thread in which I was created */ - private final Thread parent; - - /** A runnable target (if any) */ - private final Runnable target; - - /** The VM thread implementing this thread */ - private final VmThread vmThread; - /** - * Create a new default instance - * - * @see java.lang.Object#Object() + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(group, null, name)</code> + * + * @param group the group to put the Thread into + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see #Thread(ThreadGroup, Runnable, String) */ - public Thread() { - this(null, null, autoName()); + public Thread(ThreadGroup group, String name) + { + this(group, null, name); } /** - * Create a new instance with a runnable as thread runner. + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, target, name)</code>. * - * @param target + * @param target the Runnable object to execute + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @see #Thread(ThreadGroup, Runnable, String) */ - public Thread(Runnable target) { - this(null, target, autoName()); - } - - /** - * Create a new instance with a runnable as thread runner and a given name. - * - * @param target - * @param name - */ - public Thread(Runnable target, String name) { + public Thread(Runnable target, String name) + { this(null, target, name); } /** - * Create a new instance with a given name. + * Allocate a new Thread object, with the specified ThreadGroup and name, and + * using the specified Runnable object's <code>run()</code> method to + * execute. If the Runnable object is null, <code>this</code> (which is + * a Runnable) is used instead. * - * @param name + * <p>If the ThreadGroup is null, the security manager is checked. If a + * manager exists and returns a non-null object for + * <code>getThreadGroup</code>, that group is used; otherwise the group + * of the creating thread is used. Note that the security manager calls + * <code>checkAccess</code> if the ThreadGroup is not null. + * + * <p>The new Thread will inherit its creator's priority and daemon status. + * These can be changed with <code>setPriority</code> and + * <code>setDaemon</code>. + * + * @param group the group to put the Thread into + * @param target the Runnable object to execute + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see Runnable#run() + * @see #run() + * @see #setDaemon(boolean) + * @see #setPriority(int) + * @see SecurityManager#checkAccess(ThreadGroup) + * @see ThreadGroup#checkAccess() */ - public Thread(String name) { - this(null, null, name); - } - - /** - * Create a new instance with a given group as containing group and a - * runnable as thread runner. - * - * @param group - * @param target - */ - public Thread(ThreadGroup group, Runnable target) { - this(group, target, autoName()); - } - - /** - * Create a new instance with a given group as containing group, a runnable - * as thread runner and a given name. - * - * @param group - * @param target - * @param name - */ - public Thread(ThreadGroup group, Runnable target, String name) { + public Thread(ThreadGroup group, Runnable target, String name) + { Thread current = currentThread(); if (group != null) { @@ -246,7 +331,7 @@ group.addThread(this); this.group = group; - this.target = target; + this.runnable = target; this.name = name; this.parent = current; @@ -296,7 +381,7 @@ group.addThread(this); this.group = group; - this.target = target; + this.runnable = target; this.name = name; this.parent = current; @@ -328,7 +413,7 @@ group.addThread(this); ... [truncated message content] |