From: lingutln Date: Tue, 13 Dec 2011 22:54:54 +0000 (+0000) Subject: Annotation Project with new structure of packages. X-Git-Url: http://gitweb.planteome.org/?a=commitdiff_plain;h=433618da845ffc9e77b75e5f52826a3544f002c8;p=old-jaiswallab-svn%2F.git Annotation Project with new structure of packages. svn path=/; revision=223 --- diff --git a/Annotation/.classpath b/Annotation/.classpath new file mode 100644 index 0000000..156f768 --- /dev/null +++ b/Annotation/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/Annotation/.gitignore b/Annotation/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/Annotation/.project b/Annotation/.project new file mode 100644 index 0000000..e0f3845 --- /dev/null +++ b/Annotation/.project @@ -0,0 +1,17 @@ + + + Annotation + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/Annotation/.settings/org.eclipse.jdt.core.prefs b/Annotation/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..9e1a043 --- /dev/null +++ b/Annotation/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Tue Dec 13 14:02:38 PST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/Annotation/META-INF/ECLIPSE.RSA b/Annotation/META-INF/ECLIPSE.RSA new file mode 100644 index 0000000..e370c0e Binary files /dev/null and b/Annotation/META-INF/ECLIPSE.RSA differ diff --git a/Annotation/META-INF/ECLIPSE.SF b/Annotation/META-INF/ECLIPSE.SF new file mode 100644 index 0000000..662042c --- /dev/null +++ b/Annotation/META-INF/ECLIPSE.SF @@ -0,0 +1,2219 @@ +Signature-Version: 1.0 +SHA1-Digest-Manifest-Main-Attributes: 5EWAvbAiR6Q4Q79WtdyMPP5did0= +Created-By: 1.5.0 (IBM Corporation) +SHA1-Digest-Manifest: 84TjmKKEeQbxGf6FHXw8xH9Wnt4= + +Name: org/eclipse/jface/fieldassist/ControlDecoration$2.class +SHA1-Digest: iGZzlMSQnikJlp+jw0oCR4mBOgE= + +Name: org/eclipse/jface/preference/PreferencePage$3.class +SHA1-Digest: qF1zFYwLQhp4SagSACM13Hj3CbQ= + +Name: org/eclipse/jface/preference/PreferenceDialog$4.class +SHA1-Digest: jTe+5Kj0fw7HBrMorB9wnfwA+aQ= + +Name: org/eclipse/jface/preference/RadioGroupFieldEditor.class +SHA1-Digest: GvdMdbOhtG0PFj1BCRskOj/mncc= + +Name: org/eclipse/jface/dialogs/Dialog.class +SHA1-Digest: zG6Ozv8VWfsFI7UDzB8XlSeEUFM= + +Name: org/eclipse/jface/internal/JFaceActivator.class +SHA1-Digest: uCLmH9z+xLKaGimc/A2D34kztrI= + +Name: org/eclipse/jface/bindings/CachedBindingSet.class +SHA1-Digest: 7rqIEDyVwUfjsGZBymbuHjpcuZ0= + +Name: org/eclipse/jface/viewers/ViewerRow.class +SHA1-Digest: 8qoYH649iJt30GFqXWgvxGgPxVI= + +Name: org/eclipse/jface/fieldassist/IContentProposalListener.class +SHA1-Digest: tmRtj73sYnqzleK2xxiOyzE1L1k= + +Name: org/eclipse/jface/operation/AccumulatingProgressMonitor$4.class +SHA1-Digest: m2DvMWv0btAAjBlhol5Yyyi1Hjw= + +Name: org/eclipse/jface/viewers/ICellModifier.class +SHA1-Digest: MLWSDSBJALcKVtHybMcxQvrkiuw= + +Name: org/eclipse/jface/dialogs/DialogPage.class +SHA1-Digest: paRcOAFkjDH7SYEVfeqMKqVKJa0= + +Name: org/eclipse/jface/dialogs/ProgressMonitorDialog.class +SHA1-Digest: +EdvdkPTMVBPM4ecBxhkEZrKqtk= + +Name: org/eclipse/jface/action/AbstractAction.class +SHA1-Digest: w0kJoNREzOzn43LG2L5iaFwnaPc= + +Name: org/eclipse/jface/viewers/StructuredViewer$ColorAndFontCollector + .class +SHA1-Digest: K/6GSuix21oodCJuGwUG6ztcofw= + +Name: org/eclipse/jface/dialogs/IconAndMessageDialog.class +SHA1-Digest: nYuOeO2gOZtFkL31QpAAvvBrjVI= + +Name: org/eclipse/jface/fieldassist/SimpleContentProposalProvider$1.cl + ass +SHA1-Digest: nxcSSDXMNp3hYPYbERVhhXDSfwU= + +Name: org/eclipse/jface/dialogs/DialogMessageArea.class +SHA1-Digest: 0pmQEGMPsY/H9zdgGsE/LdE0qKs= + +Name: org/eclipse/jface/operation/IRunnableContext.class +SHA1-Digest: /EcDpCNiCk6CuDPOVJ9/VLxELxI= + +Name: org/eclipse/jface/viewers/AbstractTreeViewer$4.class +SHA1-Digest: 0tpIkrdSqJGGtf6gLpvs5mixjoI= + +Name: org/eclipse/jface/dialogs/MessageDialogWithToggle.class +SHA1-Digest: Pc562HrcnM8tamv1cFpR2t/4AK4= + +Name: org/eclipse/jface/viewers/Viewer$2.class +SHA1-Digest: Cx2F7HkRfJfkgTCmv3fya0SJgD0= + +Name: org/eclipse/jface/action/ActionContributionItem$5.class +SHA1-Digest: jMg3zDTLAxesrNizIY+xdwPv8Wg= + +Name: org/eclipse/jface/viewers/ColumnViewerEditorActivationStrategy.c + lass +SHA1-Digest: 7jzZvzV76INEtLejjrRF0KpFMJI= + +Name: org/eclipse/jface/viewers/TreeViewerEditor.class +SHA1-Digest: 7L/k0DP2bSjtrQIQo+KgChSJML8= + +Name: org/eclipse/jface/bindings/keys/IKeyLookup.class +SHA1-Digest: 3RO+TXrY+GUrNbqfPdXdS/umgF8= + +Name: org/eclipse/jface/viewers/TableViewerEditor.class +SHA1-Digest: YOBbpDpgWafz8nz4AFar85A7xoI= + +Name: org/eclipse/jface/viewers/AbstractTableViewer$1.class +SHA1-Digest: 90MbjrI3u2AXcS3vs2ztUNUlp9g= + +Name: org/eclipse/jface/viewers/StructuredViewer$8.class +SHA1-Digest: 36SQLLvrPr8LTXtO4/9+mFaI1vc= + +Name: org/eclipse/jface/fieldassist/ComboContentAdapter.class +SHA1-Digest: QRz+sVte5Ms73iIHkFfgsWy1i3Y= + +Name: org/eclipse/jface/action/IStatusLineManager.class +SHA1-Digest: a4GdvF+6pe+bbvRc6QJRyUaQoLk= + +Name: org/eclipse/jface/window/IShellProvider.class +SHA1-Digest: YLuzbe/8n6jGYsAGro9+z7HrwGU= + +Name: org/eclipse/jface/viewers/ListViewer.class +SHA1-Digest: DKR66oVPaOLKJJOAIrM6Z7z+Ajo= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$1.class +SHA1-Digest: 0gy1qbGJIfonNbxdi/D6T+7RPEQ= + +Name: org/eclipse/jface/viewers/ILazyTreeContentProvider.class +SHA1-Digest: qWN0XG4Qhia6KvxFLrIPK/eVfEE= + +Name: org/eclipse/jface/viewers/TextCellEditor$4.class +SHA1-Digest: QgEz4CI4aGL5ZykOCKFuE28CDu0= + +Name: org/eclipse/jface/bindings/keys/KeySequenceText$KeyTrapListener. + class +SHA1-Digest: 0N7egGc+uYroh6YoN8QtX3UG1oA= + +Name: org/eclipse/jface/preference/PreferenceLabelProvider.class +SHA1-Digest: 89CKBoan2dnwFULZWROtmX+0Cpk= + +Name: org/eclipse/jface/action/ToolBarContributionItem$4.class +SHA1-Digest: GBm74NJU+trWLBjMR5mvo386ymA= + +Name: org/eclipse/jface/bindings/SchemeEvent.class +SHA1-Digest: hoZW87aPwR8U0YvqYaZI9HMu6C8= + +Name: org/eclipse/jface/commands/PersistentState.class +SHA1-Digest: yL3lMIitYZ+ms6h0zAmyB6SZCFk= + +Name: org/eclipse/jface/viewers/IBasicPropertyConstants.class +SHA1-Digest: lIP3Ni4M1fUH5CwarS0KMtioceg= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter.class +SHA1-Digest: rA1DcSYjmxcedjABiaEKospSAto= + +Name: org/eclipse/jface/action/ExternalActionManager.properties +SHA1-Digest: UueIvQ/nF9uuYBwcs1azcYU19uc= + +Name: org/eclipse/jface/preference/BooleanFieldEditor$1.class +SHA1-Digest: 5kEPR9EotiV4X1c6jMjI0oqK/Ns= + +Name: org/eclipse/jface/dialogs/ProgressMonitorDialog$3.class +SHA1-Digest: PyFbLevAtCrXakbSmqpXhcWajzM= + +Name: org/eclipse/jface/resource/ImageDescriptor.class +SHA1-Digest: WzgmcUKovAQ9VO4qE9zDbzxTpOk= + +Name: org/eclipse/jface/viewers/deferred/DeferredContentProvider.class +SHA1-Digest: 9Wk50rmWV3ImvRvXRG58iffbx+4= + +Name: org/eclipse/jface/window/Window$3.class +SHA1-Digest: qtonjTRSx2Lt3CMTj6DbJbaLnbA= + +Name: org/eclipse/jface/viewers/CustomHashtable$HashMapEntry.class +SHA1-Digest: tPgEFUQac0g46rfQBPdpf0vMVTU= + +Name: org/eclipse/jface/viewers/ContentViewer.class +SHA1-Digest: XRPy4VxsQalW4K3gTLZ0C/AZvCs= + +Name: org/eclipse/jface/viewers/IFontProvider.class +SHA1-Digest: g/dCUHHOCwC1gWJnqYVUuOkbLWE= + +Name: org/eclipse/jface/preference/IPersistentPreferenceStore.class +SHA1-Digest: 0h/VCibXYY6f837VN8gZHYVC9AY= + +Name: org/eclipse/jface/viewers/ISelectionChangedListener.class +SHA1-Digest: zsv0sq11yrTP//btCXjMitoyTUg= + +Name: org/eclipse/jface/viewers/CheckboxTreeViewer.class +SHA1-Digest: 2IuKVo0W0eefa1r+aXz1h54zCAQ= + +Name: org/eclipse/jface/operation/IRunnableWithProgress.class +SHA1-Digest: pU3FXK0vb68suXDN0vVqFRsVi0U= + +Name: org/eclipse/jface/bindings/keys/formatting/AbstractKeyFormatter. + properties +SHA1-Digest: qQ7mPHSVsC3AQZDzY6RmQ1DfwiA= + +Name: org/eclipse/jface/viewers/DecoratingLabelProvider.class +SHA1-Digest: vcnZjCwHH8uRYDf3nDQXm04+ZwI= + +Name: org/eclipse/jface/resource/FontRegistry$FontRecord.class +SHA1-Digest: 1eBoKicV0hgzRjOxO3Rx/ebUozg= + +Name: org/eclipse/jface/window/ToolTip$4.class +SHA1-Digest: CGbQ81V61G+73ENinJAskhr2jlY= + +Name: org/eclipse/jface/viewers/deferred/SetModel.class +SHA1-Digest: h5lrw51Xq5crMZMvRi6MWgsl76M= + +Name: org/eclipse/jface/viewers/ITableFontProvider.class +SHA1-Digest: PXD0wkY3N2bk3rpL6+CIMOu+dec= + +Name: org/eclipse/jface/preference/FieldEditor.class +SHA1-Digest: 7K4g+fddHzmlVs8G2DpfW6RY5Xg= + +Name: org/eclipse/jface/preference/StringFieldEditor$4.class +SHA1-Digest: 1n/UsXplUufL9Rt1kw8uJQOkvqE= + +Name: org/eclipse/jface/wizard/IWizard.class +SHA1-Digest: OpJzFa5/5cY1FZmwhojIvRpb15Y= + +Name: org/eclipse/jface/viewers/TreeViewer$6.class +SHA1-Digest: oYD52jDXsjqz7sYPpI+g19uH2ws= + +Name: org/eclipse/jface/fieldassist/AutoCompleteField.class +SHA1-Digest: 3N38AL22/8ZgQEatQpXjm3ZsMps= + +Name: org/eclipse/jface/action/Separator.class +SHA1-Digest: UvxUEudgExshA7J7wb5BoFESz0g= + +Name: org/eclipse/jface/resource/ColorRegistry$1.class +SHA1-Digest: f71p6xN807Y6b/y2nqF5gmzazBY= + +Name: org/eclipse/jface/bindings/keys/formatting/AbstractKeyFormatter. + class +SHA1-Digest: JijjWGplCRMUfslb2x2ncB9+6Pw= + +Name: org/eclipse/jface/preference/FontFieldEditor.class +SHA1-Digest: mEDoY6sUprGzmhKjO1dniSDCa10= + +Name: org/eclipse/jface/window/ApplicationWindow.class +SHA1-Digest: IZl1iLxQgeG+UAsoLbsEQM8RSxw= + +Name: org/eclipse/jface/viewers/StructuredViewer$3.class +SHA1-Digest: VQYLNVmwiILmm++iCDrzx+LWZEo= + +Name: org/eclipse/jface/util/DelegatingDropAdapter$2.class +SHA1-Digest: heTOuGjccnCCplk8AqdiPQYklD8= + +Name: org/eclipse/jface/fieldassist/ControlDecoration$8.class +SHA1-Digest: jI6Z36lYy2QgSdrlOR2sxyJNSNc= + +Name: org/eclipse/jface/fieldassist/DecoratedField$4.class +SHA1-Digest: iADBpnr8VrqHDJKTsSHkacaBMC8= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$10.class +SHA1-Digest: FAxocK04ZrFWJFeAMtCAs+9CRJo= + +Name: org/eclipse/jface/preference/RadioGroupFieldEditor$2.class +SHA1-Digest: AJVgCJqIuJFv2xiltX4vRp4VoQY= + +Name: org/eclipse/jface/resource/AbstractResourceManager.class +SHA1-Digest: KknrjuPVMJyKGhIyeALK1NhGbKo= + +Name: org/eclipse/jface/action/StatusLineManager$1.class +SHA1-Digest: jE5hBsg9R+QrrP3IIr2ZZ10Ug9A= + +Name: org/eclipse/jface/preference/ColorSelector$1.class +SHA1-Digest: bMvVHd/a7h/77azt3YgqdnCYsPU= + +Name: org/eclipse/jface/viewers/deferred/BackgroundContentProvider.cla + ss +SHA1-Digest: 5roAVac/frvjMj67eyWqhEIKEIU= + +Name: org/eclipse/jface/action/StatusLine$2.class +SHA1-Digest: G+r8KY3LMsnDaqaKfhWAmSJ+9Qg= + +Name: org/eclipse/jface/dialogs/MessageDialog.class +SHA1-Digest: N374r8GdoJv197GWY9mqNH5eJwA= + +Name: org/eclipse/jface/dialogs/IDialogBlockedHandler.class +SHA1-Digest: tKloZ49QXCFTDoMfu1Vb2+MxJtQ= + +Name: org/eclipse/jface/wizard/WizardDialog$6.class +SHA1-Digest: GqUX7gcsWOQaipxTsfDEuylDye8= + +Name: org/eclipse/jface/viewers/deferred/AbstractVirtualTable.class +SHA1-Digest: brnlUiB6TTYrfbSsYrcFQkdnv7Y= + +Name: org/eclipse/jface/viewers/IFontDecorator.class +SHA1-Digest: 891zp1j09NBrzqwkKlmW6pm/1+U= + +Name: org/eclipse/jface/preference/PreferenceDialog$15.class +SHA1-Digest: wTJzQ/mvWex9xus+cCxH5esrbhs= + +Name: org/eclipse/jface/viewers/deferred/AbstractConcurrentModel.class +SHA1-Digest: Pl29R9jkzZNC/ahl5xDa1TrFOEE= + +Name: org/eclipse/jface/viewers/SelectionChangedEvent.class +SHA1-Digest: D0XjDa8cFH1VCo6lbeTMx/FQkws= + +Name: org/eclipse/jface/viewers/CheckboxTreeViewer$1.class +SHA1-Digest: TNNQiMqPUJud17cCPA2IEFcw+Og= + +Name: org/eclipse/jface/wizard/WizardSelectionPage.class +SHA1-Digest: uE3H+08Tiu1/bqHwyx2gXgfWe3o= + +Name: org/eclipse/jface/viewers/SWTFocusCellManager$1.class +SHA1-Digest: JwDhPhtCJhYEkzul0sQa0iCjwqg= + +Name: org/eclipse/jface/dialogs/PopupDialog$5.class +SHA1-Digest: IGv9QPtbXGBGrCFLlICFjvhF6uI= + +Name: org/eclipse/jface/fieldassist/ControlDecoration.class +SHA1-Digest: Wymg79Vuh3R2r18c3reOJiOzNto= + +Name: org/eclipse/jface/viewers/ComboBoxCellEditor$4.class +SHA1-Digest: 2Mv9grE6uGu+MLdLZaUPzTXHf8A= + +Name: org/eclipse/jface/viewers/OwnerDrawLabelProvider$2.class +SHA1-Digest: SpYWw9tEhqwiWSOsnDNqB2mrb3E= + +Name: org/eclipse/jface/resource/FontDescriptor.class +SHA1-Digest: eT5gH5T1mgfxlTl/DeD9o/+2xcQ= + +Name: org/eclipse/jface/preference/PreferencePage.class +SHA1-Digest: fkGGQdxuSvXQhwO/6nTr4s2pFSs= + +Name: org/eclipse/jface/util/PropertyChangeEvent.class +SHA1-Digest: EajgzipEUA6FJYIyyR8HlDUaJuU= + +Name: org/eclipse/jface/fieldassist/DecoratedField$Hover.class +SHA1-Digest: CwXHp+oid5QN8CC/agHhYygRu/0= + +Name: org/eclipse/jface/dialogs/PageChangingEvent.class +SHA1-Digest: EzH4BwyIhpqgE4NpiDdYb77D2RI= + +Name: org/eclipse/jface/viewers/IDecorationContext.class +SHA1-Digest: uo0idfey67ODyrk3PuQe0JBR1Co= + +Name: org/eclipse/jface/viewers/deferred/ConcurrentTableUpdator$1.clas + s +SHA1-Digest: D4I8+a7OEFF+9scpYvL8fPNE35U= + +Name: org/eclipse/jface/wizard/WizardDialog.class +SHA1-Digest: j3QiBHFGoqNYM9lYRlKjJACLmxo= + +Name: org/eclipse/jface/viewers/IInputProvider.class +SHA1-Digest: +4gWEOSXC6MMfxwKnaxLWuHxC+c= + +Name: org/eclipse/jface/fieldassist/IContentProposalProvider.class +SHA1-Digest: Me8Rz5jWeHYl8X6CEASTGEOjXng= + +Name: org/eclipse/jface/window/SameShellProvider.class +SHA1-Digest: D+ZZxaND3T79NvHygMhumBnTezU= + +Name: org/eclipse/jface/action/IContributionManagerOverrides.class +SHA1-Digest: XT0XSk1MLNZgd1GM64ODnBmwKeM= + +Name: org/eclipse/jface/util/DelegatingDragAdapter$1.class +SHA1-Digest: 9fux831/DeidfEcSTMrOkGOicBU= + +Name: org/eclipse/jface/window/Window.class +SHA1-Digest: f2LgB6JO8pAE3znhtDOhHtOsPbU= + +Name: org/eclipse/jface/fieldassist/IControlContentAdapter.class +SHA1-Digest: X56J3Fu2l9LAmCgRSEygaTm/E2Q= + +Name: org/eclipse/jface/util/Policy$1.class +SHA1-Digest: FdI6d9oWZD67J54iUPVuU07nlyE= + +Name: org/eclipse/jface/viewers/ColumnPixelData.class +SHA1-Digest: 3hM93QKuNRIeZy7kMUSzW3G2bjc= + +Name: org/eclipse/jface/bindings/keys/formatting/FormalKeyFormatter.cl + ass +SHA1-Digest: NLAxKJ3zlljxjxs4Qtf1U1JEaEg= + +Name: org/eclipse/jface/resource/jfacefonts_hp-ux.properties +SHA1-Digest: DdgNeYu/6JwIhnA+ziuY1MfdoMY= + +Name: org/eclipse/jface/window/ApplicationWindow$1.class +SHA1-Digest: pZkzltYH/pT7NJT6JoBaOLA2e/w= + +Name: org/eclipse/jface/viewers/TreeViewer$1.class +SHA1-Digest: vDSjOG6fISzrQOq+81/A0NXaeak= + +Name: org/eclipse/jface/bindings/keys/KeySequenceText$1.class +SHA1-Digest: T7wVfH1jsrxsAwFuDwOw2VujKuI= + +Name: org/eclipse/jface/fieldassist/FieldDecoration.class +SHA1-Digest: yxaNFae07DcPFqt2cS9kkPgyQgE= + +Name: org/eclipse/jface/resource/URLImageDescriptor.class +SHA1-Digest: xfpFtZYPkTeIkKwUPH7bVYuI0eE= + +Name: org/eclipse/jface/bindings/Binding.class +SHA1-Digest: qUbUSRqzW5b60ay9Stc2r0XhA8E= + +Name: org/eclipse/jface/util/OpenStrategy$4.class +SHA1-Digest: Q34pdgB010llEvChdiVxC7HRZmc= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$7.class +SHA1-Digest: i7tNTnZWospqj0NsfD+Cb3O1nvM= + +Name: org/eclipse/jface/viewers/ColumnViewerEditor.class +SHA1-Digest: qT62vM+iZ793659vi43YypCpRjI= + +Name: org/eclipse/jface/preference/ColorFieldEditor.class +SHA1-Digest: mPMTPU8DZsIHQTfCRx8M2ghvs7s= + +Name: org/eclipse/jface/action/IToolBarManager.class +SHA1-Digest: i+c+nu4vep+zBSrZuORi3Sc/b8o= + +Name: org/eclipse/jface/dialogs/DialogTray.class +SHA1-Digest: 5jxPOwxsY0mRt7x6q1ADmpQ5tk4= + +Name: org/eclipse/jface/bindings/ISchemeListener.class +SHA1-Digest: MMWaPQ7IW9t4niSnqpOqkk2J2ug= + +Name: org/eclipse/jface/resource/ColorRegistry.class +SHA1-Digest: ghlErnokdMnUppnC5Rg64UspcYk= + +Name: org/eclipse/jface/layout/TreeColumnLayout$TreeLayoutListener.cla + ss +SHA1-Digest: 70Vw7oLYGelbGNaXCxT7JoAp7ko= + +Name: org/eclipse/jface/viewers/BaseLabelProvider$1.class +SHA1-Digest: VJ0cyhBjSbI1mJUv63hSalGJKYQ= + +Name: org/eclipse/jface/fieldassist/ControlDecoration$3.class +SHA1-Digest: Mm3k4+hXRB2D0n0mMc8FLM0MebE= + +Name: org/eclipse/jface/viewers/IColorProvider.class +SHA1-Digest: 8DcdSk9zjqjd/JtQUfu3j6/h/gQ= + +Name: org/eclipse/jface/preference/PreferencePage$4.class +SHA1-Digest: lknbKDfMDxyQskxfxKKxN1GCJ9Q= + +Name: org/eclipse/jface/resource/ImageRegistry.class +SHA1-Digest: 8gXTaXNH5orPlV5rTOOg7MzXXR0= + +Name: org/eclipse/jface/viewers/ViewerColumn.class +SHA1-Digest: e2VIRAB1IO+iCFTJEchSoiz3XF8= + +Name: org/eclipse/jface/viewers/ViewerComparator.class +SHA1-Digest: EBmM3EbHDfVZThgHARGD4cT6Wyw= + +Name: org/eclipse/jface/action/ToolBarManager.class +SHA1-Digest: C7ImvSN0ik3hKhB/r6tWPjEtdrg= + +Name: org/eclipse/jface/viewers/deferred/IConcurrentModel.class +SHA1-Digest: FNQSCi9PiBLCYeAzDohidY6sP5w= + +Name: org/eclipse/jface/action/IContributionItem.class +SHA1-Digest: bXDHmVshoXP39HMPjpqJz0NuwK8= + +Name: org/eclipse/jface/preference/PreferenceDialog$5.class +SHA1-Digest: 4JsPFuoXAugqDDTWI5r5en2z3hY= + +Name: org/eclipse/jface/internal/provisional/action/ToolBarManager2.cl + ass +SHA1-Digest: 5+YgtcblKrsWfrixChkGIYI9VUg= + +Name: org/eclipse/jface/viewers/BaseLabelProvider.class +SHA1-Digest: /5bVcq79HIp/BwtP46v/pFMPIhk= + +Name: org/eclipse/jface/wizard/WizardDialog$1.class +SHA1-Digest: IvzKz6Xl699zp2RS/tAJDVRgWgE= + +Name: org/eclipse/jface/preference/PreferenceDialog$10.class +SHA1-Digest: Bg2Kn2uLL08EWFb+4HAimWZkOzc= + +Name: org/eclipse/jface/viewers/ITreePathLabelProvider.class +SHA1-Digest: 8Nb2jUmFJW0Jn+LeSAYeweeo2Ew= + +Name: org/eclipse/jface/viewers/LabelProviderChangedEvent.class +SHA1-Digest: mbQZ/j6whMi4RcB8mjBveK7zcTE= + +Name: org/eclipse/jface/action/ToolBarContributionItem.class +SHA1-Digest: C9BtCUPurPzQewoeYCwFDrdZGR8= + +Name: org/eclipse/jface/action/LegacyActionTools.class +SHA1-Digest: P57JOvtufqnWZsMqVEdHjcNEwxo= + +Name: org/eclipse/jface/operation/AccumulatingProgressMonitor$5.class +SHA1-Digest: GKMNPGNT2UZQRMo09apctBBvFpo= + +Name: org/eclipse/jface/viewers/SWTFocusCellManager.class +SHA1-Digest: MP6fa7q73TKIJX8Uv7BSUp4qIqE= + +Name: org/eclipse/jface/viewers/OwnerDrawLabelProvider.class +SHA1-Digest: kbzmkO9H7tDizrX1aAszpA/Wj3U= + +Name: org/eclipse/jface/action/SubToolBarManager.class +SHA1-Digest: e15sVyMVIa81F9VydWgI+l7fPqs= + +Name: org/eclipse/jface/viewers/ColumnLayoutData.class +SHA1-Digest: wR/4YK+DCcWF+TqH+EPnfEnI6lI= + +Name: org/eclipse/jface/util/ISafeRunnableRunner.class +SHA1-Digest: C4a7MwkgoLP1QXl3fkLZXbIjYqM= + +Name: org/eclipse/jface/util/TransferDropTargetListener.class +SHA1-Digest: 6FZoSxMHKoPfstPic/1GMQlktc8= + +Name: org/eclipse/jface/fieldassist/FieldDecorationRegistry$Entry.clas + s +SHA1-Digest: xruXtxS3oTQD7qVLiZjFbWq4Kzc= + +Name: org/eclipse/jface/viewers/DialogCellEditor$1.class +SHA1-Digest: wiz/rzkV2RcqrTYLiYroFTHf5xo= + +Name: org/eclipse/jface/viewers/AbstractTreeViewer$5.class +SHA1-Digest: zaDihpPtfDGrwSrbdPwpW4EPw/A= + +Name: org/eclipse/jface/viewers/DoubleClickEvent.class +SHA1-Digest: aYLfn0r6mq8YUfky0Iom6C4mg5E= + +Name: org/eclipse/jface/fieldassist/IContentProposal.class +SHA1-Digest: odEBYrDVhWgkCWdC1ABLvXBBl+o= + +Name: org/eclipse/jface/action/ActionContributionItem$6.class +SHA1-Digest: UsE4FYilN88afT9IkOsK71pY8CY= + +Name: org/eclipse/jface/viewers/AbstractListViewer$1.class +SHA1-Digest: UEQ3dWFrwQJ56Q6bXMzvgGxMKI8= + +Name: org/eclipse/jface/bindings/keys/KeyLookupFactory.class +SHA1-Digest: +XqDeX8VBAEJp53sdpg4E9sKmUA= + +Name: org/eclipse/jface/viewers/AbstractTableViewer$2.class +SHA1-Digest: Vi0qeWuO/PIJKNe2PuAI7xH9wso= + +Name: org/eclipse/jface/action/IMenuCreator.class +SHA1-Digest: kieVrrSWjOqN28wXYLHKDjzOg90= + +Name: org/eclipse/jface/viewers/TableTreeViewer$1.class +SHA1-Digest: f6aAKLuJn0bhKCMDJDTBNOIodrg= + +Name: org/eclipse/jface/viewers/StructuredViewer$9.class +SHA1-Digest: ClRZsrmpOwGpCvwAubTFNfpFmkI= + +Name: org/eclipse/jface/menus/AbstractTrimWidget.class +SHA1-Digest: /fEqZ6WMBxIOHILszWWszkZtcmw= + +Name: org/eclipse/jface/viewers/ViewerCell.class +SHA1-Digest: XvPDw5i/CSGXMM3hV4j+yv9Qwpo= + +Name: org/eclipse/jface/viewers/AbstractListViewer.class +SHA1-Digest: VEzvbObT+6LuhCaQ6hBgF852BTc= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$2.class +SHA1-Digest: +7+8Z9qHzaXfVjLdbWC0qrUpyBg= + +Name: org/eclipse/jface/viewers/ComboViewer.class +SHA1-Digest: 9fR3KEGUr2OiW2h7zHb1DBj6Pco= + +Name: org/eclipse/jface/viewers/TextCellEditor$5.class +SHA1-Digest: eHLnVLxCl8i6msLemooRW7oJ4xM= + +Name: org/eclipse/jface/wizard/Wizard.class +SHA1-Digest: LazrshzZld3IMGIrmlX/hH/uF40= + +Name: org/eclipse/jface/dialogs/InputDialog.class +SHA1-Digest: Fp0WtGtRPp/9AJRVFAyCO81KR/M= + +Name: org/eclipse/jface/viewers/IInputSelectionProvider.class +SHA1-Digest: MZI5TJ9X1919Jkk8lkgpbEX8dc0= + +Name: org/eclipse/jface/resource/FontRegistry.class +SHA1-Digest: xB+IDR83HvKXJStlHG87e6rR16s= + +Name: org/eclipse/jface/viewers/TreeViewerColumn.class +SHA1-Digest: Yc6eUSCm/cmfBsMAYumBRUv9j84= + +Name: org/eclipse/jface/action/ExternalActionManager.class +SHA1-Digest: cPFGv9W+qowqdUdaA4MmCLfmxU8= + +Name: org/eclipse/jface/action/ICoolBarManager.class +SHA1-Digest: SsIS4rnUWyYkuY2nOs5l5rXr3EU= + +Name: org/eclipse/jface/viewers/TableViewerColumn.class +SHA1-Digest: 2qd3dEc1q04dyEowPw624ZvF97M= + +Name: org/eclipse/jface/dialogs/DialogSettings.class +SHA1-Digest: 79eryhvFMtUJ5lgxebp1v4QHZZ0= + +Name: org/eclipse/jface/resource/AbstractResourceManager$RefCount.clas + s +SHA1-Digest: LiZU6gMUXyxQDMWWqn2tny7XAcY= + +Name: org/eclipse/jface/preference/ColorSelector.class +SHA1-Digest: vYzAt0XEUxYV4isQaBFxiD0C9V8= + +Name: org/eclipse/jface/action/StatusLineManager.class +SHA1-Digest: yVxa+rR0vV8a2p76wuu5dkubmb8= + +Name: org/eclipse/jface/preference/BooleanFieldEditor$2.class +SHA1-Digest: KGKiEM5qjLC/kMYRuS3RyNHefqQ= + +Name: org/eclipse/jface/viewers/ViewerSorter.class +SHA1-Digest: 8h50w1p2p1PFPmPdMc3iosjcJ0Y= + +Name: org/eclipse/jface/dialogs/ProgressIndicator.class +SHA1-Digest: rGsMOj7x4nT9+UE/z04O4hKA/8k= + +Name: org/eclipse/jface/viewers/TreeColumnViewerLabelProvider$1.class +SHA1-Digest: LayPvFXQFPFIOB72JEhVJ5/J/Oo= + +Name: org/eclipse/jface/window/ApplicationWindow$ApplicationWindowLayo + ut.class +SHA1-Digest: DYR+N03EEHLYLAgKosledVrh1vI= + +Name: org/eclipse/jface/action/CoolBarManager.class +SHA1-Digest: QEzBDIxP6BXcPEKKSr1Iy/gxtNo= + +Name: org/eclipse/jface/fieldassist/FieldDecorationRegistry.class +SHA1-Digest: Gqr8/Y9YF7qdXEnEypAjd18XsLI= + +Name: org/eclipse/jface/viewers/IOpenListener.class +SHA1-Digest: LkdnUxquMcFT9cE12C0Rr39PLwQ= + +Name: org/eclipse/jface/preference/FieldEditor$1.class +SHA1-Digest: ncOEYR67CeB+YDPHOVDFLEGaDPc= + +Name: org/eclipse/jface/preference/IPreferencePage.class +SHA1-Digest: rNfcBt1JT6gR3RHOc82WxhjhQNA= + +Name: org/eclipse/jface/preference/BooleanFieldEditor.class +SHA1-Digest: tI75Elc7BcBxkahHXb0fmkfVqvw= + +Name: org/eclipse/jface/viewers/ITableLabelProvider.class +SHA1-Digest: k/fkWmJL0Z/pbnEjoHXtK9xxSZU= + +Name: org/eclipse/jface/util/SafeRunnableDialog$1.class +SHA1-Digest: gRS/fSnSA8k1VgfqJ6p3s1u2kWY= + +Name: org/eclipse/jface/layout/AbstractColumnLayout.class +SHA1-Digest: f/ByQWIeY0o9i77B9xmCP9XdG/o= + +Name: org/eclipse/jface/viewers/StructuredViewer$ColorAndFontCollector + WithProviders.class +SHA1-Digest: 0lcbRO1FqTxlPOYp4r5CQKwzubU= + +Name: org/eclipse/jface/internal/provisional/action/IToolBarManager2.c + lass +SHA1-Digest: kXWlyfzHabQlbfj+HnZ/5hfXqK8= + +Name: org/eclipse/jface/preference/ColorFieldEditor$1.class +SHA1-Digest: /dlrN7rz7cGYiKw+ymGS0JAMg/A= + +Name: org/eclipse/jface/action/SubCoolBarManager.class +SHA1-Digest: 3S9WsZ1ty0oENw1hkGSi4C6M5qk= + +Name: plugin.properties +SHA1-Digest: tWNH3hrisFHSrwmu2D5aiafbnjw= + +Name: org/eclipse/jface/action/ActionContributionItem$1.class +SHA1-Digest: TFpLnlsSJIZhyyqHWFxV0icGVj8= + +Name: org/eclipse/jface/bindings/keys/formatting/NativeKeyFormatter.pr + operties +SHA1-Digest: Hi7YkOmGtbLmnfhvmhwGOJy0mLQ= + +Name: org/eclipse/jface/window/ToolTip.class +SHA1-Digest: TaTQGa/W1JCTtNn9/aHlYdMW++4= + +Name: org/eclipse/jface/dialogs/ProgressMonitorDialog$ProgressMonitor. + class +SHA1-Digest: ADo2Enwrh9VAIYhx0eGEpP+N+/s= + +Name: org/eclipse/jface/bindings/IBindingManagerListener.class +SHA1-Digest: dc6u6FbL/18eNjT71elM3xdOj9Q= + +Name: org/eclipse/jface/preference/ComboFieldEditor$1.class +SHA1-Digest: qFgA2vKOcH6inGwrZhEhJnnY5XE= + +Name: org/eclipse/jface/viewers/ColumnViewer$1.class +SHA1-Digest: iz5SYN6ITjkuL0Qjthf37rF5Aho= + +Name: org/eclipse/jface/dialogs/ErrorDialog$1.class +SHA1-Digest: 6D/zwylihOWzoZEZV+kOV27KUiE= + +Name: org/eclipse/jface/viewers/ICheckStateListener.class +SHA1-Digest: OV9Nl3s2BO9SJ3FsqDJpAbTuhg8= + +Name: org/eclipse/jface/dialogs/TrayDialog.class +SHA1-Digest: MOh+A0wmNDwUD+mJwSbG8JRS/QE= + +Name: org/eclipse/jface/viewers/StructuredViewer$4.class +SHA1-Digest: ip8lX75vIV+lmBMBALS6SObisow= + +Name: org/eclipse/jface/viewers/IStructuredSelection.class +SHA1-Digest: 2tK+qLoIYEVAHeZsAknZWaP81Cg= + +Name: org/eclipse/jface/util/DelegatingDropAdapter$3.class +SHA1-Digest: 9gSxvKNaCXDrw8efwKEHX3pQvos= + +Name: org/eclipse/jface/fieldassist/DecoratedField$5.class +SHA1-Digest: 0jLFM4I3R9GAX5crkraZ82ZQZmE= + +Name: org/eclipse/jface/viewers/TreeViewer.class +SHA1-Digest: GN/nRmwm7nY2okxXifzNLCSljTQ= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$11.class +SHA1-Digest: CGcS4ZFi37GyVUoAJiQTSJ8lMGk= + +Name: org/eclipse/jface/action/AbstractGroupMarker.class +SHA1-Digest: XQnug1YGBO0kQJO6MQRVDZpdFX0= + +Name: org/eclipse/jface/menus/IMenuStateIds.class +SHA1-Digest: yOEupcQIPltveAoeYJ9O0mgXIDE= + +Name: org/eclipse/jface/preference/ColorSelector$2.class +SHA1-Digest: bsH9bjZUChnZnzpn9c+PfH9+AwM= + +Name: org/eclipse/jface/viewers/ILazyContentProvider.class +SHA1-Digest: lspzBOZYqKBFQe1uN2QkD0KwZXM= + +Name: org/eclipse/jface/action/StatusLine$3.class +SHA1-Digest: je2hwk5H86vP06oYxuce5TqXpuw= + +Name: org/eclipse/jface/action/MenuManager.class +SHA1-Digest: w/Bn0jkvfT25xHfhqwtFS4BQ0ug= + +Name: org/eclipse/jface/wizard/IWizardNode.class +SHA1-Digest: X/fmztQYyvWDgMV0KsNv+ih23WQ= + +Name: org/eclipse/jface/fieldassist/images/required_field_cue.gif +SHA1-Digest: kFgJwSfgjrz6DeAnyTG8VwiYBro= + +Name: org/eclipse/jface/viewers/IDelayedLabelDecorator.class +SHA1-Digest: v7JhOkUsV2uR7TQyAUSJ8ll2lII= + +Name: org/eclipse/jface/viewers/SWTFocusCellManager$2.class +SHA1-Digest: mybS+mcAjjKwYStuiXB8Xw9gALc= + +Name: org/eclipse/jface/viewers/ILabelDecorator.class +SHA1-Digest: fIvm/v7b86gWCRMVsBpm1/EpXGQ= + +Name: org/eclipse/jface/dialogs/PopupDialog$6.class +SHA1-Digest: JxolexrtUJ8/4r25uSSal7mn1Ho= + +Name: org/eclipse/jface/viewers/OwnerDrawLabelProvider$3.class +SHA1-Digest: EuR5vMrQ+HR/wifGMLjmayZxhWs= + +Name: org/eclipse/jface/viewers/ColumnViewerEditorDeactivationEvent.cl + ass +SHA1-Digest: 4xZJLS/ZALs2kxTN1rQt1VurDSY= + +Name: org/eclipse/jface/dialogs/ControlAnimator.class +SHA1-Digest: cpu/ClpckOMkv+scejHIQGqJU5A= + +Name: org/eclipse/jface/resource/jfacefonts_sunos.properties +SHA1-Digest: HrsLzqtlY256rEtTO16bpSdax4c= + +Name: org/eclipse/jface/fieldassist/images/contassist_ovr.gif +SHA1-Digest: 57qSW9uQioUmE5UdvgvmFM8F+b0= + +Name: org/eclipse/jface/viewers/CellEditor$LayoutData.class +SHA1-Digest: I6whnxT8y74ZaGRq+gHGe5bJ3j4= + +Name: org/eclipse/jface/resource/jfacefonts_linux_gtk.properties +SHA1-Digest: Oo2DBUcSZfvWdidnAFd6RKVFHrw= + +Name: org/eclipse/jface/dialogs/IconAndMessageDialog$1.class +SHA1-Digest: +aiCa3azGCdIliM7kCO26GoeN50= + +Name: org/eclipse/jface/util/SafeRunnable.class +SHA1-Digest: 3YyIwI9dR006n4vFQ6zPzQJpv3Y= + +Name: META-INF/eclipse.inf +SHA1-Digest: SAqY+5ITAL0mkdYeijlSRhyIaZk= + +Name: org/eclipse/jface/layout/AbstractColumnLayout$1.class +SHA1-Digest: uftACdFIsdtuxsTknO5MIeCVIFw= + +Name: org/eclipse/jface/util/DelegatingDragAdapter$2.class +SHA1-Digest: A7/v7QBKBYyFeNiQO0gtzPMz6FQ= + +Name: org/eclipse/jface/dialogs/PageChangedEvent.class +SHA1-Digest: WIEUtq749x6EYR6qUTFO6s9BXyE= + +Name: org/eclipse/jface/util/Policy$2.class +SHA1-Digest: el4nezY2lboq2UA4cEQVvp+DFyk= + +Name: org/eclipse/jface/preference/ListEditor$1.class +SHA1-Digest: hOS4vTAwITe63OK69gRtrgdGvfY= + +Name: org/eclipse/jface/dialogs/PopupDialog$PersistBoundsAction.class +SHA1-Digest: q3r/UgLWuZYH027UVQ1ijbRuywg= + +Name: org/eclipse/jface/viewers/deferred/DeferredContentProvider$Table + ViewerAdapter.class +SHA1-Digest: v4PTzyzSS/bNn2x31k8dS1VH4MM= + +Name: org/eclipse/jface/preference/PreferenceStore.class +SHA1-Digest: iHIiOHR1kcn10bvJJqhWqcoDFUA= + +Name: org/eclipse/jface/viewers/TreeViewerFocusCellManager.class +SHA1-Digest: Rg33tiTXenal1c2q7KsWbIg4Vxg= + +Name: org/eclipse/jface/preference/FontFieldEditor$1.class +SHA1-Digest: D95MQhuRclaek/BfU9j6G+4JIzU= + +Name: org/eclipse/jface/viewers/ColumnViewerEditor$1.class +SHA1-Digest: lvHU+SbHKPlAYsrhA514+l8T8sI= + +Name: org/eclipse/jface/dialogs/images/message_info.gif +SHA1-Digest: 4+5SUEYuS/dj4a895j9IOruyRMY= + +Name: org/eclipse/jface/dialogs/ControlEnableState$ItemState.class +SHA1-Digest: MNcQJ60aixDqZgIyFFeOGA1fudU= + +Name: org/eclipse/jface/resource/FileImageDescriptor.class +SHA1-Digest: mNk+JLnHPWQbdAFaCa+OZ3kX6kw= + +Name: org/eclipse/jface/viewers/TreeViewer$2.class +SHA1-Digest: 0bHaCc7F8zeV/hDl/f1nwNvUL4g= + +Name: org/eclipse/jface/bindings/keys/KeySequenceText$2.class +SHA1-Digest: RL67nF6sxbH1BT7xkNMaZ63pdas= + +Name: org/eclipse/jface/viewers/CheckboxTableViewer$1.class +SHA1-Digest: sk0LD9EDw+X2tvFOgGxPlClIJqU= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$8.class +SHA1-Digest: t0pjQVNqMRqxwJdjC9/BvOZSD5g= + +Name: org/eclipse/jface/viewers/StructuredViewer$UpdateItemSafeRunnabl + e.class +SHA1-Digest: uMBa4hk48TSMlVv6ufekAsZZwu8= + +Name: org/eclipse/jface/viewers/CheckboxCellEditor.class +SHA1-Digest: fxy0K42NYAEraNzB0zmJ65Xc2DM= + +Name: org/eclipse/jface/viewers/TreeSelection$InitializeData.class +SHA1-Digest: ZRPxfeO9CZpleerkNJnnTG9TJ14= + +Name: org/eclipse/jface/bindings/keys/KeySequenceText.class +SHA1-Digest: MTtYd60chLP3u/JyQhN2PIiQbBw= + +Name: org/eclipse/jface/fieldassist/ControlDecoration$4.class +SHA1-Digest: al2vN1FYLYpSMHMCAxokIPATtOk= + +Name: org/eclipse/jface/fieldassist/IContentProposalListener2.class +SHA1-Digest: I5IQUeHrSrr0RNUuN2LA5fD/sfw= + +Name: org/eclipse/jface/window/ToolTip$TooltipHideListener.class +SHA1-Digest: AWowHswa0UE/EOOAhC6SYztBPJo= + +Name: org/eclipse/jface/viewers/IBaseLabelProvider.class +SHA1-Digest: CcLat4gZgEPhu/B2W4WMQlnlC5I= + +Name: org/eclipse/jface/util/OpenStrategy.class +SHA1-Digest: T0mxgRh4jSaKco8V4MCNtuVqfV4= + +Name: org/eclipse/jface/preference/PreferenceDialog$6.class +SHA1-Digest: 7PcTTaLAGPxbyetOasLBK/b6Wjo= + +Name: org/eclipse/jface/wizard/WizardDialog$2.class +SHA1-Digest: 8uA3wtws8z7jD43kdW+r8vnw34A= + +Name: org/eclipse/jface/util/SafeRunnable$1.class +SHA1-Digest: 2umWrfjksQ0MS70+JG2x2RzbLAY= + +Name: org/eclipse/jface/preference/PreferenceDialog$11.class +SHA1-Digest: O02NzqZ0AbJKtR+2NCYptxcgSgM= + +Name: org/eclipse/jface/resource/LocalResourceManager$1.class +SHA1-Digest: jpcFMI4RCk5T966O5yLGI/lP7rQ= + +Name: org/eclipse/jface/viewers/deferred/IntHashMap.class +SHA1-Digest: o6kUSud7+tn1YgigbdcAju/O8ug= + +Name: org/eclipse/jface/viewers/CellEditor$1.class +SHA1-Digest: Mr9pauGbra0I693a/ptImT7QNTY= + +Name: org/eclipse/jface/dialogs/images/help.gif +SHA1-Digest: 0yYw/cn9njN3clSzHx43MdH0L7k= + +Name: org/eclipse/jface/action/StatusLine.class +SHA1-Digest: kzn2ZEdHZIUeJYd95zXPGZ9D07Q= + +Name: org/eclipse/jface/dialogs/PopupDialog$1.class +SHA1-Digest: VWwFVyqkzncebypKrPsWlYQ5S3o= + +Name: org/eclipse/jface/contexts/IContextIds.class +SHA1-Digest: DDvZqTHQrgoS8gP7axmOLICx2S4= + +Name: org/eclipse/jface/viewers/TreeNodeContentProvider.class +SHA1-Digest: jDb6XqU8SpxJb1jCjFzcCxwEHMA= + +Name: org/eclipse/jface/action/ContributionItem.class +SHA1-Digest: cYRyTsQtAPnjToLzl6ZjMy/hfQ0= + +Name: org/eclipse/jface/action/Action$1.class +SHA1-Digest: qD4GQNN/CLnK+K7WmoglJUHzTDQ= + +Name: org/eclipse/jface/preference/PreferenceDialog.class +SHA1-Digest: 2D9l2J3eK+35A6dz+z6WxmcgVgY= + +Name: org/eclipse/jface/layout/LayoutConstants.class +SHA1-Digest: yX2rsxqXNPU5sCfYsVUR9QxzTuA= + +Name: org/eclipse/jface/viewers/TreeViewerFocusCellManager$1.class +SHA1-Digest: X81rPyD+S5fd7kuwoVVMrFpa2xY= + +Name: org/eclipse/jface/viewers/TableColumnViewerLabelProvider.class +SHA1-Digest: 9HqbbhBAsNP2f5i3+7CyC0ALW8M= + +Name: org/eclipse/jface/viewers/IColorDecorator.class +SHA1-Digest: BWmbSGHnKYvj2Dh/DteJ4bjUCNY= + +Name: org/eclipse/jface/viewers/ILightweightLabelDecorator.class +SHA1-Digest: kbo1qzUrH3zJV+I4GJ4WYhJW37A= + +Name: org/eclipse/jface/operation/AccumulatingProgressMonitor$Collecto + r.class +SHA1-Digest: D5ShG7fV9bGwCiCOH/HqHahMIMc= + +Name: org/eclipse/jface/viewers/DialogCellEditor$2.class +SHA1-Digest: snWPTjmEFYjOXdgJykp5WD3nBgo= + +Name: org/eclipse/jface/viewers/AbstractTreeViewer$6.class +SHA1-Digest: vg6+OjDls3q+Cj1LIAGgBeBf1JA= + +Name: org/eclipse/jface/resource/ImageDataImageDescriptor.class +SHA1-Digest: DtD9W5VBTkzJWIvPamlI2whyxxM= + +Name: org/eclipse/jface/dialogs/TrayDialog$1.class +SHA1-Digest: 3UC9Kt03AvXFuUEjAxkUK3AV7S0= + +Name: org/eclipse/jface/util/DelegatingDragAdapter.class +SHA1-Digest: HEm5T4B0tN97W71IQJHkuxkl/ME= + +Name: org/eclipse/jface/internal/provisional/action/ToolBarContributio + nItem2.class +SHA1-Digest: 7NFzkt09eqSgxjsqTOZSN8/kd/0= + +Name: org/eclipse/jface/viewers/TableViewer$1.class +SHA1-Digest: LC6wzgZN/wfh3UraLeZFFE80SPs= + +Name: org/eclipse/jface/viewers/AbstractTableViewer$3.class +SHA1-Digest: b6kXtpeNnCl0tx2H1/CSghMyh5Y= + +Name: org/eclipse/jface/util/ListenerList.class +SHA1-Digest: JRJeqTnvP2boO9uai9RqVB94gOI= + +Name: org/eclipse/jface/resource/JFaceResources.class +SHA1-Digest: aBrxtrcskDguKeazeyN6LeXTjiM= + +Name: org/eclipse/jface/viewers/TableTreeViewer$2.class +SHA1-Digest: JdoC3DlW5WKUwKNSeqyOaW6Eeno= + +Name: org/eclipse/jface/util/LocalSelectionTransfer.class +SHA1-Digest: xzoMAPMzcDGE7EikpP41APaTenY= + +Name: org/eclipse/jface/preference/StringFieldEditor.class +SHA1-Digest: hwIsBB9NjnOJkV9XuJ1DIUtwLm4= + +Name: org/eclipse/jface/action/ExternalActionManager$1.class +SHA1-Digest: 1WRJ6ds7CVEcEbVII/YjjyBN1Qo= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$3.class +SHA1-Digest: T5UsNG6YLa+//AKyPrXFLUG4/Ho= + +Name: org/eclipse/jface/viewers/WrappedViewerLabelProvider.class +SHA1-Digest: cdGH5ez8CNa4MzvRw3PCrUt+hC4= + +Name: org/eclipse/jface/viewers/TextCellEditor$6.class +SHA1-Digest: Njh00JUQgN9MHQuTdI0SrWLBz5I= + +Name: org/eclipse/jface/viewers/AbstractTableViewer.class +SHA1-Digest: EG7QRmsCmDmAon+tAwth25np7qo= + +Name: org/eclipse/jface/operation/ModalContext$1.class +SHA1-Digest: zrfgG4topJmDQxmT/TGLPpaV/SI= + +Name: org/eclipse/jface/action/ControlContribution.class +SHA1-Digest: 9IIz8uXykWOv7BrbG3FKwax8qVs= + +Name: org/eclipse/jface/bindings/Scheme.class +SHA1-Digest: n35jC969b3ntgi+35SH+MVZO6vY= + +Name: org/eclipse/jface/preference/PreferenceDialog$1.class +SHA1-Digest: A0X4U+JozQ5bpnMZ5dnxKdX42jU= + +Name: org/eclipse/jface/preference/PreferenceStore$1.class +SHA1-Digest: 01ON1xif/rXBcumyCBomc8WUaEY= + +Name: org/eclipse/jface/resource/LocalResourceManager.class +SHA1-Digest: bCV1WrTJ9PvyU+0N2MZoxgvTcrM= + +Name: org/eclipse/jface/resource/DeviceResourceDescriptor.class +SHA1-Digest: nlVoMy25VQqSg3kq6dYnXH9ySUg= + +Name: org/eclipse/jface/operation/AccumulatingProgressMonitor$1.class +SHA1-Digest: /AzVTwzR5tozuEwYPHJlzhhtIu0= + +Name: org/eclipse/jface/util/SafeRunnableDialog$2.class +SHA1-Digest: fvMnOCEMp1oh6O+jh025+Wn+P2A= + +Name: org/eclipse/jface/dialogs/IMessageProvider.class +SHA1-Digest: jtqJpxCW3PevB3d0w8G1duZSQZc= + +Name: org/eclipse/jface/fieldassist/images/warn_ovr.gif +SHA1-Digest: QinaeVEnreHLqsEwedtOOmgyv9Q= + +Name: org/eclipse/jface/bindings/BindingManagerEvent.class +SHA1-Digest: lMe5xyhkfCpuxXj88lUc0KtswF8= + +Name: org/eclipse/jface/preference/PreferenceConverter.class +SHA1-Digest: HMRPHyQ6nY8s5WlcVEnXessWmwM= + +Name: org/eclipse/jface/operation/AccumulatingProgressMonitor.class +SHA1-Digest: c/mTOmIPdA06EK03KIWbmFpE0jM= + +Name: org/eclipse/jface/bindings/keys/KeySequenceText$TraversalFilter. + class +SHA1-Digest: u3c557X0JoNUTbacV6WwXeY8RMA= + +Name: org/eclipse/jface/viewers/AbstractTreeViewer$1.class +SHA1-Digest: ZeRLuay83LgukkB/mePMfrXGfi8= + +Name: org/eclipse/jface/preference/IPreferencePageContainer.class +SHA1-Digest: /KfDDJ25D9yh1qmw/PfvLCS+uqg= + +Name: org/eclipse/jface/viewers/CustomHashtable.class +SHA1-Digest: oqESqdnwGRChPAgfopSQlu+EZqQ= + +Name: org/eclipse/jface/action/ActionContributionItem$2.class +SHA1-Digest: 1zi9buG+O1MFNklL5LFFvcZzPgo= + +Name: org/eclipse/jface/viewers/ColumnViewer$2.class +SHA1-Digest: bLlDGWKfdwjMvgp3kiGGg53/gNg= + +Name: org/eclipse/jface/viewers/StructuredViewer$5.class +SHA1-Digest: 1/CO04abNoxxMr9jtI0fnton1AM= + +Name: org/eclipse/jface/action/ToolBarManager$1.class +SHA1-Digest: aNYdmr+bnL9pl4sapwQXHlAYC5o= + +Name: org/eclipse/jface/util/DelegatingDropAdapter$4.class +SHA1-Digest: 8Hal+63xM4XsoHyOppkphaGyGDw= + +Name: org/eclipse/jface/viewers/AbstractTreeViewer.class +SHA1-Digest: wKz0Wo41oX43cnST0s4md/jBVVU= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$12.class +SHA1-Digest: kh2CM6jdnIUNfyG+282GJzeIuTU= + +Name: org/eclipse/jface/viewers/CheckStateChangedEvent.class +SHA1-Digest: Ksus+UUE8tLT+SYKEV39ZJmLu0c= + +Name: org/eclipse/jface/action/ExternalActionManager$ICallback.class +SHA1-Digest: oJZaOdjbc14XnVnpSuFcGiaiHXE= + +Name: org/eclipse/jface/preference/ColorSelector$3.class +SHA1-Digest: kJN187i+2VU+gpx09+nrkbzSWIA= + +Name: org/eclipse/jface/preference/IPreferenceStore.class +SHA1-Digest: etOMu/+F26Hd4DQ4KkQWoXnSS0w= + +Name: org/eclipse/jface/commands/ActionHandler$1.class +SHA1-Digest: kFsiZrJvnHz+KzTZcfXupcur3Cg= + +Name: org/eclipse/jface/action/StatusLine$4.class +SHA1-Digest: njb6+cRh3pIXNlrC48vDj1TO7aM= + +Name: org/eclipse/jface/viewers/TextCellEditor$1.class +SHA1-Digest: JqelNAvQD3QOoG4eQ5lFCAJhbuQ= + +Name: org/eclipse/jface/preference/FileFieldEditor.class +SHA1-Digest: 7ysHkCAetehqJ1fJ37FT/sS652c= + +Name: org/eclipse/jface/resource/JFaceColors.class +SHA1-Digest: daJm7rWnOWWo+gNUVYTq7evSuhg= + +Name: org/eclipse/jface/viewers/ContentViewer$1.class +SHA1-Digest: Tb2gpdo/UFpbU6tYXXetzGKSZkk= + +Name: org/eclipse/jface/action/ToolBarContributionItem$1.class +SHA1-Digest: 4agIFkSYnP6ZG8eDb9AKy6TKwY8= + +Name: org/eclipse/jface/viewers/SWTFocusCellManager$3.class +SHA1-Digest: NivKVpSWAl0azOv0HnW05x+iCb8= + +Name: org/eclipse/jface/viewers/ColorCellEditor.class +SHA1-Digest: 1eYDNxHZ2akrgbxKPqk5KB6LgLk= + +Name: org/eclipse/jface/dialogs/PopupDialog$7.class +SHA1-Digest: +yf4gB57nfKVmo/u4tQNwptAa0w= + +Name: org/eclipse/jface/viewers/OpenEvent.class +SHA1-Digest: 1XwKuWw+QBj+I3EwXmTt31jrado= + +Name: org/eclipse/jface/viewers/ViewerDropAdapter.class +SHA1-Digest: mlvfm7I8PgwWpTh/lDohNk+ax84= + +Name: org/eclipse/jface/resource/DeviceResourceException.class +SHA1-Digest: uxAb9MGXDAiCL5RGXF2ZjhpimDU= + +Name: org/eclipse/jface/wizard/ProgressMonitorPart$1.class +SHA1-Digest: NiC6gjQ5rX5449Yb8M5bnPGdj0s= + +Name: org/eclipse/jface/layout/TableColumnLayout.class +SHA1-Digest: XMzM+DeJTdp22sAn/x/Hyt2VJFw= + +Name: org/eclipse/jface/util/TransferDragSourceListener.class +SHA1-Digest: Lo+s2yClbDS/EOSaLAh0t8LknRU= + +Name: org/eclipse/jface/resource/ImageRegistry$Entry.class +SHA1-Digest: QLTfXd/FfRauy2UDzd7vc4j4ODg= + +Name: org/eclipse/jface/dialogs/IconAndMessageDialog$2.class +SHA1-Digest: QmnFoW7LvPgnpOzwddsZ7pXdEFM= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProp + osalPopup$InfoPopupDialog.class +SHA1-Digest: 46FdyvKh6mxXeXggcOd+79FMORU= + +Name: org/eclipse/jface/action/ExternalActionManager$CommandCallback.c + lass +SHA1-Digest: y1BMAs9flPxZTeHzWuOg7mt4uBA= + +Name: org/eclipse/jface/viewers/ILabelProviderListener.class +SHA1-Digest: 7lvrA7c4Tu134DZ/RkkAq0+FkWI= + +Name: org/eclipse/jface/preference/FontFieldEditor$DefaultPreviewer.cl + ass +SHA1-Digest: SGcmnjbSBLnFLzCe/+1jq9NxWGg= + +Name: org/eclipse/jface/menus/IWidget.class +SHA1-Digest: aUOhQ5T6SKmfDMgKY+KkmtY4fHs= + +Name: org/eclipse/jface/util/DelegatingDragAdapter$3.class +SHA1-Digest: X9F2HmEVsPY7vDHwx/qZItNU4bc= + +Name: org/eclipse/jface/viewers/ColorCellEditor$ColorCellLayout.class +SHA1-Digest: YBMAPPB9vChppwxBXfJwh39UWmk= + +Name: org/eclipse/jface/action/IMenuListener2.class +SHA1-Digest: R/MdrqiSzQ37sbpZiCk1phECly8= + +Name: org/eclipse/jface/viewers/ViewerFilter.class +SHA1-Digest: t+nuhqWFFJGZxb6aSB9AjA/C3Q8= + +Name: org/eclipse/jface/viewers/CellNavigationStrategy.class +SHA1-Digest: t7zgt9DFW69vZjfZyKkM54oaVds= + +Name: org/eclipse/jface/preference/ListEditor$2.class +SHA1-Digest: uqBpVSQXSFff7+XV8whd07w0Am0= + +Name: org/eclipse/jface/preference/FontFieldEditor$2.class +SHA1-Digest: 4n9mTboTrvaf5IqBpiAS/t77Ntc= + +Name: org/eclipse/jface/window/ToolTip$1.class +SHA1-Digest: Xr4jmabxBEobgAbGzhobygnHHUg= + +Name: org/eclipse/jface/viewers/ColumnViewerEditor$2.class +SHA1-Digest: u5RtLUKtMTAOPY5cgnwK2WTxbYE= + +Name: org/eclipse/jface/preference/PathEditor.class +SHA1-Digest: +S4cC3zj6w1IBwlZLsUv7oLm6dg= + +Name: org/eclipse/jface/viewers/IContentProvider.class +SHA1-Digest: yO0/5uvnhqoVnY0aoU252XGQMqs= + +Name: org/eclipse/jface/preference/StringFieldEditor$1.class +SHA1-Digest: +h7PqEUBPHe9dVs6Glb6p+1SW4s= + +Name: org/eclipse/jface/viewers/deferred/ConcurrentTableUpdator$Range. + class +SHA1-Digest: tSTzSK2AFHyShaKYKt55KlkEH8M= + +Name: org/eclipse/jface/viewers/TreeViewer$3.class +SHA1-Digest: 6pGLDoOZ2l8SN7Emn70NXcesheA= + +Name: org/eclipse/jface/viewers/FocusCellOwnerDrawHighlighter$1.class +SHA1-Digest: di6v+upJFKG9ucL8nqeAZoMDUak= + +Name: org/eclipse/jface/viewers/AcceptAllFilter.class +SHA1-Digest: mcK5dWzxY79h0gqQQwmfRj2sJi0= + +Name: org/eclipse/jface/preference/BooleanPropertyAction$1.class +SHA1-Digest: /H3QjxH6oIwXZ3MpjLK/xDAtzQ4= + +Name: org/eclipse/jface/resource/ImageRegistry$OriginalImageDescriptor + .class +SHA1-Digest: kndwQlmwG27f7lud7fivGfkQtMo= + +Name: org/eclipse/jface/action/IMenuManager.class +SHA1-Digest: VxAA0V4YTQA3UPbS5R6qAtIr00s= + +Name: org/eclipse/jface/fieldassist/SimpleContentProposalProvider.clas + s +SHA1-Digest: Bi7F4UWh+bvk/arpKt4yxVD9izU= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$9.class +SHA1-Digest: 2P94ZJ12gAxYXNlALN095JT5v5U= + +Name: org/eclipse/jface/viewers/ViewerColumn$1.class +SHA1-Digest: C1JLtvjyhOVTgNwEC3Cb5UmVGLI= + +Name: org/eclipse/jface/viewers/ViewerComparator$1.class +SHA1-Digest: rHUhe73OefEuXW6/ogyqxHRICOQ= + +Name: org/eclipse/jface/viewers/FocusCellOwnerDrawHighlighter.class +SHA1-Digest: AHrjof87KQ32jSl9vIl7GXYzkso= + +Name: org/eclipse/jface/fieldassist/DecoratedField$FieldDecorationData + .class +SHA1-Digest: gvli4Yn6/gdUOr9bkCdhROLyhPE= + +Name: org/eclipse/jface/dialogs/IPageChangingListener.class +SHA1-Digest: 9l898ZRjO5QC9/xRt+uJEPTnD7w= + +Name: org/eclipse/jface/dialogs/StatusDialog.class +SHA1-Digest: 1XZHKZ+Dxjqy4M8Sz7QEBD8nw8s= + +Name: org/eclipse/jface/preference/FieldEditorPreferencePage.class +SHA1-Digest: RXV/bhU+SPhdEalBQRjfzQiIyEw= + +Name: org/eclipse/jface/viewers/IFilter.class +SHA1-Digest: xYCE0vSQQClAf9RIryXODSxmwlA= + +Name: org/eclipse/jface/fieldassist/DecoratedField$1.class +SHA1-Digest: imMe4RZwy4njTnzTVBTC55+O8pc= + +Name: org/eclipse/jface/fieldassist/ControlDecoration$5.class +SHA1-Digest: 7g1of9yrG55ajsiiXQCMi8HYKtg= + +Name: org/eclipse/jface/action/ActionContributionItem.class +SHA1-Digest: ZTy4o3pmBswP5IHjC53tkPfFIU0= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProp + osalPopup$TargetControlListener.class +SHA1-Digest: fbI6CQYQYD5vXLoMUPiYCYWe1xY= + +Name: org/eclipse/jface/dialogs/images/popup_menu.gif +SHA1-Digest: 22R9N09vLbsIdT7NXQIXEHLO9Lk= + +Name: org/eclipse/jface/action/IContributionManager.class +SHA1-Digest: v105cSPG9w6fKeCpKB1384IAEoc= + +Name: org/eclipse/jface/viewers/StructuredSelection.class +SHA1-Digest: sBcdpWLl1DYHvRZTuUaGe252vLo= + +Name: org/eclipse/jface/resource/jfacefonts_windows98.properties +SHA1-Digest: 2yI7jAy587B/b3gaeKWlR0yberc= + +Name: org/eclipse/jface/preference/PreferenceDialog$7.class +SHA1-Digest: p+VppDoo7MPNXkgks/RjC0c+mA0= + +Name: org/eclipse/jface/bindings/BindingManager.class +SHA1-Digest: HANyKX7b2pD/ZLFiNdmIUY7EcAM= + +Name: org/eclipse/jface/resource/ColorDescriptor.class +SHA1-Digest: r5iwKsHsxYahtFRBj4NhOBHT4yo= + +Name: org/eclipse/jface/wizard/WizardDialog$3.class +SHA1-Digest: B/mhds/Dw7TMMDiCXBuXgqEeTzA= + +Name: org/eclipse/jface/util/SafeRunnable$2.class +SHA1-Digest: wZfQcCu8Vt5cb6ZEbofrjvA3FdE= + +Name: org/eclipse/jface/preference/PreferenceDialog$12.class +SHA1-Digest: rvbB9G8QjqV2s4wk84T1p6hGmM0= + +Name: org/eclipse/jface/viewers/CellEditor$2.class +SHA1-Digest: RBTKXY1Ob8f8082JrPE5+cD4qVU= + +Name: org/eclipse/jface/operation/IThreadListener.class +SHA1-Digest: EJR/R98/auL8qd4/lZMVvd9SNg0= + +Name: org/eclipse/jface/dialogs/PopupDialog$2.class +SHA1-Digest: 9ubZ1tB2EbVm2bM61gESQ3CagnQ= + +Name: org/eclipse/jface/viewers/TableViewerRow.class +SHA1-Digest: DPZa2Mk4rUkY3Ge95wDQoBRovX8= + +Name: org/eclipse/jface/viewers/ComboBoxCellEditor$1.class +SHA1-Digest: 8x7+fw7HQSwPwCGavBa1/BLX58A= + +Name: org/eclipse/jface/action/IAction.class +SHA1-Digest: L5aIwRXcSCe6jRjtCxBqbun8lOk= + +Name: org/eclipse/jface/action/ContributionManager.class +SHA1-Digest: UjLZPx2pIBQdiezA9eH9iQGWtlw= + +Name: org/eclipse/jface/viewers/ISelectionProvider.class +SHA1-Digest: 2Xv8rrqYG9g9QQM0YkBJzs57iK4= + +Name: org/eclipse/jface/internal/provisional/action/CoolBarManager2.cl + ass +SHA1-Digest: idvQDUsvxH0pNAOitAiCBTNpQAw= + +Name: org/eclipse/jface/viewers/CellEditor.class +SHA1-Digest: eCKjKtb0DiHyo/whTjJypi6LcB0= + +Name: org/eclipse/jface/viewers/TreeColumnViewerLabelProvider.class +SHA1-Digest: oDKx3wSOOD/S+AHKfPVJzs/f0Qk= + +Name: org/eclipse/jface/dialogs/IDialogSettings.class +SHA1-Digest: U72D0RrHbbyIGs0bfpr9+jIulqw= + +Name: org/eclipse/jface/viewers/ILazyTreePathContentProvider.class +SHA1-Digest: c+Ba//yLYhEJ/vJfueHLJe0HYPw= + +Name: org/eclipse/jface/viewers/IViewerLabelProvider.class +SHA1-Digest: 9YjMuwc6VGf1I5QZk6nf32f7MrI= + +Name: org/eclipse/jface/resource/ArrayFontDescriptor.class +SHA1-Digest: 0lHb3Pue2/Xeef5+H4MQXPfinbw= + +Name: org/eclipse/jface/viewers/deferred/FastProgressReporter.class +SHA1-Digest: n9yEl7X1i6XW66E/5aiqRgKUCK4= + +Name: org/eclipse/jface/dialogs/DialogSettings$XMLWriter.class +SHA1-Digest: vTc8cA23Ik0PTcK59zdr2npDJ4c= + +Name: org/eclipse/jface/viewers/DialogCellEditor$3.class +SHA1-Digest: Uc1DM1H3WpMM/Jmt9WVVQXV9inQ= + +Name: org/eclipse/jface/viewers/AbstractTreeViewer$7.class +SHA1-Digest: k+CzVBX+X4dBv1Rwi90RKsFvSRk= + +Name: org/eclipse/jface/bindings/keys/SWTKeySupport.class +SHA1-Digest: WxRlv19w5l+xtjFRy2WlGJFo0Dc= + +Name: org/eclipse/jface/dialogs/TrayDialog$2.class +SHA1-Digest: zA+C3XqZnE0zQtB8lg9pBsdb2/U= + +Name: org/eclipse/jface/viewers/IDoubleClickListener.class +SHA1-Digest: QJtV0uJ0RWPasHqjyTNwnx08Fjg= + +Name: org/eclipse/jface/resource/DataFormatException.class +SHA1-Digest: 7CkkwzusO6V1BkM6lxgpMZJyUg0= + +Name: org/eclipse/jface/util/Policy.class +SHA1-Digest: dcIT60UbzgaEyJv+nyepyQ+w8pY= + +Name: org/eclipse/jface/viewers/TableTreeViewer$3.class +SHA1-Digest: BWsEft/KoCOeMQJnP4gesv0VlCg= + +Name: org/eclipse/jface/preference/ScaleFieldEditor$1.class +SHA1-Digest: 5DLE3inzefSlmXvCRKO4l0H1eUA= + +Name: org/eclipse/jface/fieldassist/TextControlCreator.class +SHA1-Digest: OS0lxF4rUfjxim3NVeguh1GWtqk= + +Name: org/eclipse/jface/resource/jfacefonts_aix.properties +SHA1-Digest: mMrn0dBjkyVAqngF/nJgdZKuiCE= + +Name: org/eclipse/jface/resource/ImageRegistry$1.class +SHA1-Digest: GPBar2cqFQ6LKsiaA3m9V3yVrO4= + +Name: org/eclipse/jface/bindings/keys/SWTKeyLookup.class +SHA1-Digest: BpnGjNXP0fF/+JxzEe42zZHOfhg= + +Name: org/eclipse/jface/action/MenuManager$1.class +SHA1-Digest: O6Y5HoPqUa1El/T25ZkF3IbNqNw= + +Name: org/eclipse/jface/dialogs/images/popup_menu_disabled.gif +SHA1-Digest: srJeylJlVeUWnJbChgrmd/099NU= + +Name: org/eclipse/jface/action/ExternalActionManager$2.class +SHA1-Digest: FapsCo5Kpq4h46GwzXnbwekOekM= + +Name: org/eclipse/jface/util/OpenStrategy$1.class +SHA1-Digest: 0vIKHu+LBVxDc2VsRGtcU9z2rPc= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$4.class +SHA1-Digest: wMcvrqnMlGj4k3Sf6OPQI62EMBQ= + +Name: org/eclipse/jface/preference/BooleanPropertyAction.class +SHA1-Digest: xdpLLDpKyzwCZxOMJLWX9tt83cE= + +Name: org/eclipse/jface/dialogs/IPageChangeProvider.class +SHA1-Digest: 33KEh4FFykggcUvH0cLKhOot+b4= + +Name: org/eclipse/jface/wizard/IWizardPage.class +SHA1-Digest: a9+A7BQQkKb0C5X/NVEfv2xMzDU= + +Name: org/eclipse/jface/bindings/keys/formatting/NativeKeyFormatter.cl + ass +SHA1-Digest: nNeirgwng3yQKzbAWBq0yXhfpX4= + +Name: org/eclipse/jface/preference/PreferenceContentProvider.class +SHA1-Digest: TXHe4L7LXxEdG0n4fxoYT4KjNR0= + +Name: org/eclipse/jface/viewers/TableTreeViewer.class +SHA1-Digest: vNWTlEJEdfV6dO0rkzwVOn6XWOU= + +Name: org/eclipse/jface/resource/ResourceRegistry.class +SHA1-Digest: IOlJqFf+m30Kba/HN8/2Z0JH9X4= + +Name: org/eclipse/jface/preference/PreferencePage$1.class +SHA1-Digest: jLLkIcssdCNQQ/9NkOQZIVjjS+E= + +Name: org/eclipse/jface/fieldassist/images/error_ovr.gif +SHA1-Digest: TK9Xs4Ma2nrknYgS1Uklk4YAfSM= + +Name: org/eclipse/jface/viewers/CustomHashtable$HashEnumerator.class +SHA1-Digest: Uu37f/plY1D80mic7y8t9Kzinng= + +Name: org/eclipse/jface/menus/TextState.class +SHA1-Digest: 7g5CAqZojYeU3Rm9RGK/vdBxflM= + +Name: org/eclipse/jface/operation/ModalContext$ModalContextThread.clas + s +SHA1-Digest: /yE4JccpKtBesg2AJlbf6LY6ZZ8= + +Name: org/eclipse/jface/preference/PreferenceDialog$2.class +SHA1-Digest: eB0vqHEJNbMfR9Qfx3mawiKrNW8= + +Name: org/eclipse/jface/fieldassist/DecoratedField.class +SHA1-Digest: eWEI1/CKrCJEuR+Kyg9W8/6ZxM8= + +Name: org/eclipse/jface/dialogs/ImageAndMessageArea$1.class +SHA1-Digest: PXMLexLRLhj6zPb5S+097PgFJeo= + +Name: org/eclipse/jface/viewers/ITreeViewerListener.class +SHA1-Digest: J+vdR9Oz9XXy6s3YPB/8CxDT86Y= + +Name: about.html +SHA1-Digest: M+fykt9heyWoEv1LNiIEeBhi/2Q= + +Name: org/eclipse/jface/commands/RadioState.class +SHA1-Digest: dnjLILvfgNta2HYMH4lar7XhbzM= + +Name: org/eclipse/jface/viewers/ArrayContentProvider.class +SHA1-Digest: aYmv1zcRQFD5ATDaEEmL06W56qs= + +Name: org/eclipse/jface/preference/PreferenceManager.class +SHA1-Digest: uarelCwb7g6CbiNeRL8CMoNtK4s= + +Name: org/eclipse/jface/operation/AccumulatingProgressMonitor$2.class +SHA1-Digest: blI9FoBo6jfXM6qPyNC2P66BQR8= + +Name: org/eclipse/jface/bindings/TriggerSequence.class +SHA1-Digest: EUa2iHMv4Q2XmImCqWq/w7Vtwvw= + +Name: org/eclipse/jface/util/SafeRunnableDialog$3.class +SHA1-Digest: nVRwnWunMDAXQh7QVuhuJr1CUe0= + +Name: org/eclipse/jface/viewers/LabelDecorator.class +SHA1-Digest: gvHUWKGx7wppMggBC0ks0kzUnts= + +Name: org/eclipse/jface/action/SubMenuManager.class +SHA1-Digest: 0Md+/otvaw/ER4iqGu7zwECmWIM= + +Name: org/eclipse/jface/viewers/TableTreeViewer$TableTreeEditorImpl.cl + ass +SHA1-Digest: fdZ61E/DAYVHbuLVK3Zu1Oi9zUA= + +Name: org/eclipse/jface/resource/StringConverter.class +SHA1-Digest: gUPkCjqtAhSx0BjOyJN1AfkkOUY= + +Name: org/eclipse/jface/viewers/AbstractTreeViewer$2.class +SHA1-Digest: 9DhGiE90W8u/nM6zTaiEmMMv+4c= + +Name: org/eclipse/jface/wizard/images/page.gif +SHA1-Digest: cQM0Fq+6Z8epnE5peRkHHEm2ayQ= + +Name: org/eclipse/jface/action/ActionContributionItem$3.class +SHA1-Digest: 3IVcA8A2blqOrSEM/CJJf7mgT6U= + +Name: org/eclipse/jface/action/SubContributionItem.class +SHA1-Digest: oaR20nnISgYYwkwsVh0x/CdjxGg= + +Name: org/eclipse/jface/viewers/ICellEditorListener.class +SHA1-Digest: bIgZl5hilWT8ONJglpXG2+lD9lI= + +Name: org/eclipse/jface/viewers/deferred/LazySortedCollection$1.class +SHA1-Digest: i2+jtJseLuyEDTrpn7fFQq1W0Yk= + +Name: org/eclipse/jface/viewers/ColumnViewer$3.class +SHA1-Digest: f2CbE/zhXzc5QxbYzKV8QRYL4+c= + +Name: org/eclipse/jface/resource/FontRegistry$1.class +SHA1-Digest: BNdXtUNnzdXAtonMtO+inUTaSYM= + +Name: org/eclipse/jface/viewers/StructuredViewer$6.class +SHA1-Digest: Zuvuc3FgTGtFoCiMEhM3b7Ke2qs= + +Name: org/eclipse/jface/util/DelegatingDropAdapter$5.class +SHA1-Digest: STQH4pMPS95e3IvOVMx5F7jXAv4= + +Name: org/eclipse/jface/viewers/LabelProvider.class +SHA1-Digest: rWbjVohCUCmM0No8WPHujncSy4E= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$13.class +SHA1-Digest: Pr5/0MDJVbOWl2Y3EH1/zZnZhqU= + +Name: org/eclipse/jface/internal/provisional/action/ICoolBarManager2.c + lass +SHA1-Digest: u0tSlPBuPJYOS+zX4M8L0SLHCEk= + +Name: org/eclipse/jface/viewers/TableViewer.class +SHA1-Digest: NCdDifsh8iVwz3Ktfpj4D2Q6RFc= + +Name: org/eclipse/jface/wizard/WizardDialog$PageContainerFillLayout.cl + ass +SHA1-Digest: SblVjeNMPGVvykTHHg5raLfjahA= + +Name: org/eclipse/jface/resource/jfacefonts.properties +SHA1-Digest: pLlTRGmJKGTnjwooLyohaqVVP1Q= + +Name: org/eclipse/jface/viewers/TextCellEditor$2.class +SHA1-Digest: RBpQmD8f3qL40iSphQ6W1R7xc5Y= + +Name: org/eclipse/jface/action/StatusLine$StatusLineLayout.class +SHA1-Digest: yF+wk875Ggz/Op8tTDT/hOJ2+GM= + +Name: org/eclipse/jface/viewers/ContentViewer$2.class +SHA1-Digest: PEjUSpFy6gXQr0rHKuuN1VAel+Y= + +Name: org/eclipse/jface/action/ToolBarContributionItem$2.class +SHA1-Digest: mZgkllYMKqQiHrWwA5vYcgAdWeU= + +Name: org/eclipse/jface/dialogs/TitleAreaDialog.class +SHA1-Digest: 44UXOjW+XFMC5/yaCcKQs6HFGBk= + +Name: org/eclipse/jface/viewers/StructuredViewer.class +SHA1-Digest: SWxwhUBQk+6h+npZolDNTFPlknc= + +Name: org/eclipse/jface/commands/ActionHandler.class +SHA1-Digest: ym9jCNObCU4o8zZqlZolaulvZQs= + +Name: org/eclipse/jface/dialogs/ProgressMonitorDialog$1.class +SHA1-Digest: Ki3luz87q8F/TQAgkktuJXA3AQo= + +Name: org/eclipse/jface/window/Window$1.class +SHA1-Digest: qJxw+zNqd2wl4GZODZwyW04CEbA= + +Name: org/eclipse/jface/action/SubMenuManager$1.class +SHA1-Digest: 7LQtCfIC1p6IV0A6zoNgPwolGcQ= + +Name: org/eclipse/jface/dialogs/PopupDialog$ResizeAction.class +SHA1-Digest: voMjeDoBoqW/6LT3m1bXW6WHSpo= + +Name: org/eclipse/jface/dialogs/images/title_banner.gif +SHA1-Digest: wBwKg54T7FuojhG33rUCNeYEsBk= + +Name: org/eclipse/jface/layout/TreeColumnLayout$1.class +SHA1-Digest: zKwlYf3OSat9W4KdWfFVAzgW324= + +Name: org/eclipse/jface/window/Window$IExceptionHandler.class +SHA1-Digest: Cg90thTLd8sZLgnp0HvEP9nBFug= + +Name: org/eclipse/jface/preference/ListEditor$3.class +SHA1-Digest: oy8Km+UVzYMhZvVRpq/bN+IPT+U= + +Name: org/eclipse/jface/commands/RadioState$RadioStateManager$RadioGro + up.class +SHA1-Digest: YiUCaSO3gZRUo07ojpZ1quUjR0s= + +Name: org/eclipse/jface/preference/FontFieldEditor$3.class +SHA1-Digest: geSmCsbAPUpU30hx3tzhR+v0JTE= + +Name: org/eclipse/jface/viewers/ColumnViewerEditor$3.class +SHA1-Digest: ZNeAwT+JTNTYIU+elZMGHHZ/i+I= + +Name: org/eclipse/jface/window/ToolTip$2.class +SHA1-Digest: ZEWNxaczvH/GE/lN+h7d6RWgYek= + +Name: org/eclipse/jface/preference/StringFieldEditor$2.class +SHA1-Digest: GtkSrN6aJFLvjK25EyHKAXHBrvo= + +Name: org/eclipse/jface/viewers/deferred/LazySortedCollection$Edge.cla + ss +SHA1-Digest: FjMZiTyah3/2WP0BEOC8IFOj6SU= + +Name: org/eclipse/jface/viewers/TableViewerFocusCellManager.class +SHA1-Digest: n1u3zMuOVbmHcFn94RjpJOBqXUw= + +Name: org/eclipse/jface/viewers/TreeViewer$4.class +SHA1-Digest: udYOLAS/2ufp/M3DERlUmmAXm30= + +Name: org/eclipse/jface/util/ILogger.class +SHA1-Digest: eNX1IaWuQk87dxk6lcEJffTsmu0= + +Name: org/eclipse/jface/viewers/ColumnViewerEditorActivationEvent.clas + s +SHA1-Digest: +Lr0yRFP9kj7amR2ED+uBDZZcF8= + +Name: org/eclipse/jface/viewers/ITableColorProvider.class +SHA1-Digest: wmgsAB35SwZM8BwNOtLCmreFyr0= + +Name: org/eclipse/jface/viewers/ILabelProvider.class +SHA1-Digest: r6gLAjAFliFIrTFVPUmWB/D1X8M= + +Name: org/eclipse/jface/viewers/TreeSelection.class +SHA1-Digest: f4joIQKmTe+Juw2OCgznJc+aO6M= + +Name: org/eclipse/jface/util/SafeRunnableDialog.class +SHA1-Digest: 7AuaaK/kLjP1+nLq2EQbBP9mf7A= + +Name: org/eclipse/jface/viewers/deferred/IConcurrentModelListener.clas + s +SHA1-Digest: AlSsuiWv/1RO84RuUb4FViH02ic= + +Name: org/eclipse/jface/viewers/deferred/BackgroundContentProvider$1.c + lass +SHA1-Digest: 8LTW5qNI97wLj9WPEBN4CJSz93s= + +Name: org/eclipse/jface/dialogs/InputDialog$1.class +SHA1-Digest: wP0WAu37Lj+h6aZq76bcwWLAKJg= + +Name: org/eclipse/jface/bindings/keys/formatting/EmacsKeyFormatter.cla + ss +SHA1-Digest: 0hUeaT8c6mHWJd/+oBvfBCnIYs0= + +Name: org/eclipse/jface/viewers/ViewerColumn$2.class +SHA1-Digest: C7s9vbHbmf0W4BATxnGysnm4Ixs= + +Name: org/eclipse/jface/action/ExternalActionManager$IActiveChecker.cl + ass +SHA1-Digest: G5Nb6wPZpJCKZmEqLsAwTPrB7Xc= + +Name: org/eclipse/jface/wizard/IWizardContainer2.class +SHA1-Digest: Ty0SM2BT4G17b4ZBiKNB1tA9rvg= + +Name: org/eclipse/jface/viewers/CellLabelProvider.class +SHA1-Digest: R8a5UDueiUxjXGj92sBDgnnRAXE= + +Name: org/eclipse/jface/viewers/IStructuredContentProvider.class +SHA1-Digest: 2FTYYk0MjKz3+PCqKTNXx+21qTI= + +Name: org/eclipse/jface/viewers/StructuredViewer$1.class +SHA1-Digest: acFOO0tUKeliKUoU9S7XzRzqbVw= + +Name: org/eclipse/jface/fieldassist/DecoratedField$2.class +SHA1-Digest: TFqMD6a3zkzCguklz3gG9O3wKtk= + +Name: org/eclipse/jface/fieldassist/ControlDecoration$6.class +SHA1-Digest: Z9QZQi0F443FrjhIUiK15LTFgjY= + +Name: org/eclipse/jface/viewers/deferred/BackgroundContentProvider$Sor + tThread.class +SHA1-Digest: nz9OWBBdBQ8XzIdhiSeo3r8F2/c= + +Name: org/eclipse/jface/dialogs/Dialog$1.class +SHA1-Digest: XQZG+5/hwLwaftLYOl42OzxNOOs= + +Name: org/eclipse/jface/preference/DirectoryFieldEditor.class +SHA1-Digest: Wo0QhBmnem9HZjtBUvWwQAMm99k= + +Name: org/eclipse/jface/dialogs/IInputValidator.class +SHA1-Digest: FTjnZG1JqzG8fWtZLBBxby8w1jM= + +Name: org/eclipse/jface/preference/PreferenceDialog$8.class +SHA1-Digest: SEHUNkxUvBnTpRjoHBascUrqHgI= + +Name: org/eclipse/jface/viewers/IDecoration.class +SHA1-Digest: hFANTTYtdCm/M61HZVRyWhHSYzw= + +Name: org/eclipse/jface/window/Window$DefaultExceptionHandler.class +SHA1-Digest: AnRDjJ7LRNfS8zveCdyEeDpU5gI= + +Name: org/eclipse/jface/wizard/WizardDialog$4.class +SHA1-Digest: WFzvw1ShLrPg37mAP17gpRPa9fY= + +Name: org/eclipse/jface/preference/images/pref_dialog_title.gif +SHA1-Digest: +f9inxjFleZdqF8QasPKYtOtQts= + +Name: org/eclipse/jface/util/SafeRunnable$3.class +SHA1-Digest: Y84Q2/VKWE8ULQQX1pGZ+W/9AB4= + +Name: org/eclipse/jface/preference/PreferenceDialog$13.class +SHA1-Digest: cKrV8PIN52KBnGjXaFtPChvT2F0= + +Name: org/eclipse/jface/viewers/CellEditor$3.class +SHA1-Digest: n+8Id78pAM4vutmX36qgE8hDwoc= + +Name: org/eclipse/jface/dialogs/PopupDialog$3.class +SHA1-Digest: DIAGv99xi3dYhcVunLEWX5YZrFQ= + +Name: org/eclipse/jface/viewers/ComboBoxCellEditor$2.class +SHA1-Digest: RngLKnOZIAY+9TwE7QN165zaGU8= + +Name: org/eclipse/jface/window/Window$FontChangeListener.class +SHA1-Digest: HhKZE8ZyvdaraLNI1xoZC+oVMig= + +Name: org/eclipse/jface/viewers/ColumnWeightData.class +SHA1-Digest: U++p8SuVDhCRur15RA8iYcsNJCU= + +Name: org/eclipse/jface/viewers/TreeViewerRow.class +SHA1-Digest: BauA9NOalZJDGBQEqeU1AgOopwo= + +Name: org/eclipse/jface/layout/LayoutGenerator.class +SHA1-Digest: KYt3khyT2KxKIcOV53paU9UnPmc= + +Name: org/eclipse/jface/viewers/IPostSelectionProvider.class +SHA1-Digest: xjw5YPx5EAiAny5uJcz7sMAvhzE= + +Name: org/eclipse/jface/util/Assert$AssertionFailedException.class +SHA1-Digest: sY+Xvd2nNLy+6HJhRvFQ2wC6/vM= + +Name: org/eclipse/jface/dialogs/ImageAndMessageArea.class +SHA1-Digest: eQgMElW7NoVRCXQNviWJTTwrAxI= + +Name: org/eclipse/jface/images/dots_button.gif +SHA1-Digest: aMO48kHOSAa1q3kG1INeOUinOx0= + +Name: org/eclipse/jface/wizard/ProgressMonitorPart.class +SHA1-Digest: y+3AL8O7qaXnGcFKSnIQwJjcDW4= + +Name: org/eclipse/jface/resource/jfacefonts_macosx.properties +SHA1-Digest: vDukkesScCaSuS1N/vKDLy5vLJY= + +Name: org/eclipse/jface/dialogs/PopupDialog.class +SHA1-Digest: P7lNg0bQpNddBiVe4CY0CmYC9bY= + +Name: org/eclipse/jface/util/Util.class +SHA1-Digest: 4Zi4P2yN8kj/0RmvRKHECH19kA4= + +Name: org/eclipse/jface/viewers/ColumnViewerEditorActivationStrategy$1 + .class +SHA1-Digest: 29yx3w38rYqnPHqsbLQHcJPvsa0= + +Name: org/eclipse/jface/bindings/keys/ParseException.class +SHA1-Digest: ERt/VxrP+2MkZpZdJxJ4DnjBGfk= + +Name: org/eclipse/jface/commands/ToggleState.class +SHA1-Digest: zDUpF6DqpLgvtGMl5zDwiVGXPcI= + +Name: org/eclipse/jface/dialogs/StatusDialog$MessageLine.class +SHA1-Digest: M5vGIUZ3D67x8/NwNv2ULanAmt0= + +Name: org/eclipse/jface/viewers/AbstractTreeViewer$8.class +SHA1-Digest: HnClWObvdBQLk7rjxkQ8nLUR+y4= + +Name: org/eclipse/jface/viewers/AbstractTreeViewer$UpdateItemSafeRunna + ble.class +SHA1-Digest: zw7XcXQrg0C02MfPJUD8ktsMHrQ= + +Name: org/eclipse/jface/viewers/ITreeSelection.class +SHA1-Digest: +F8z26Op0upYoPrfA3pm1e01ebc= + +Name: org/eclipse/jface/dialogs/TrayDialog$3.class +SHA1-Digest: vq0hDaycb0Z3ppgTYHwLJvRQo0g= + +Name: org/eclipse/jface/viewers/ITreeContentProvider.class +SHA1-Digest: 7gb/bVtY4Rzl3UVgCmgg/mPQCDQ= + +Name: org/eclipse/jface/fieldassist/TextContentAdapter.class +SHA1-Digest: Ny050dfIJlel4CzOFQvfGV8UeGw= + +Name: org/eclipse/jface/bindings/keys/KeySequenceText$UpdateSequenceLi + stener.class +SHA1-Digest: ddcHLbRqDLzzy0WREs8zSu+v+sk= + +Name: org/eclipse/jface/viewers/ColumnLabelProvider.class +SHA1-Digest: VHaJNHpmiZuYwYnCJ6LvSkMCAqQ= + +Name: org/eclipse/jface/viewers/TableTreeViewer$4.class +SHA1-Digest: N9pFGoIvcHk1o+VtAr6K60swRQk= + +Name: org/eclipse/jface/preference/ScaleFieldEditor$2.class +SHA1-Digest: DbEydSGp0pewvPadWAB79W2IpOQ= + +Name: org/eclipse/jface/preference/ListEditor.class +SHA1-Digest: C5wusKhxLf/zzXV7mQIB2qDlDAY= + +Name: org/eclipse/jface/dialogs/images/message_error.gif +SHA1-Digest: 1cph4z9iIwiy2S9c0S/cYT+I3iI= + +Name: org/eclipse/jface/resource/ImageRegistry$2.class +SHA1-Digest: Q29P91VkibEPlLYuajQVG1HPFw8= + +Name: org/eclipse/jface/viewers/EditingSupport.class +SHA1-Digest: yfMP6u+HhNi6W0BSDVxlNDzANsk= + +Name: org/eclipse/jface/action/MenuManager$2.class +SHA1-Digest: ZeZPLHJZJnXEs5Z9+KTNmntNk5o= + +Name: org/eclipse/jface/util/OpenStrategy$2.class +SHA1-Digest: xM2dHa4s9ZDKYlJ2bhSqOqxLRkE= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$5.class +SHA1-Digest: EAq3sdtsWSXV3WIPP0TLtlGI48U= + +Name: org/eclipse/jface/action/GroupMarker.class +SHA1-Digest: RECukQoU4kH9MozQtUeoN4YzYX4= + +Name: org/eclipse/jface/preference/StringButtonFieldEditor$1.class +SHA1-Digest: mBHRuZaMvalRFCGXwP+FW5LPhn8= + +Name: org/eclipse/jface/viewers/TreePathViewerSorter$1.class +SHA1-Digest: 6efAh49omiCnSe5LJzZPyX8v6j8= + +Name: org/eclipse/jface/viewers/CheckboxTableViewer.class +SHA1-Digest: SBjSD0xcqjI2XLx9KytVOMoUh4k= + +Name: org/eclipse/jface/fieldassist/ControlDecoration$1.class +SHA1-Digest: fm5zmAwRHAKwrSpxPwIbZ1Es0Cc= + +Name: org/eclipse/jface/preference/PreferencePage$2.class +SHA1-Digest: BLi85lNcmPGhMUcAG4FyFmtNZRg= + +Name: org/eclipse/jface/layout/GridLayoutFactory.class +SHA1-Digest: 1ixPBQcO24d88JEznt9fOagQk9g= + +Name: org/eclipse/jface/viewers/NamedHandleObjectLabelProvider.class +SHA1-Digest: RpQ1vvqUlcYDYO7kKgG6Wp5czVs= + +Name: org/eclipse/jface/action/ContributionManager$1.class +SHA1-Digest: SX6xIgBnN7AdowIhGKbnCfpB1xY= + +Name: org/eclipse/jface/preference/StringButtonFieldEditor.class +SHA1-Digest: Gc3hsSfRxQINvVoPs7qMgzRNNWg= + +Name: org/eclipse/jface/preference/PreferenceDialog$3.class +SHA1-Digest: UI2Pr1xWjiMDmCUwKVgZeU4+MT4= + +Name: org/eclipse/jface/resource/RGBColorDescriptor.class +SHA1-Digest: Sha6puqMEpI+/CTi1WCXX0Ey9xc= + +Name: org/eclipse/jface/bindings/keys/formatting/KeyFormatterFactory.c + lass +SHA1-Digest: aduzk4wOIWaXbZe7TXENxrkkamI= + +Name: org/eclipse/jface/resource/MissingImageDescriptor.class +SHA1-Digest: GVzwDdS4Hcf5QQRdYcZs+1ZTdzg= + +Name: org/eclipse/jface/resource/jfacefonts_windowsnt.properties +SHA1-Digest: O8sXG9Pxd+YKWlI4WGbGETZerC0= + +Name: org/eclipse/jface/resource/CompositeImageDescriptor.class +SHA1-Digest: 0Q1r4JDo1ywexXXHLEFyc+mUpQg= + +Name: org/eclipse/jface/dialogs/ImageAndMessageArea$2.class +SHA1-Digest: nQjeywsE58mq4F+cWud6DJtrfSY= + +Name: org/eclipse/jface/viewers/ITreePathContentProvider.class +SHA1-Digest: c3U1VZfwTMXr77Imuv7z1KQSgY4= + +Name: org/eclipse/jface/operation/ModalContext.class +SHA1-Digest: MIyvgca76IoeDGrcKUOTf1+zVAs= + +Name: org/eclipse/jface/viewers/ICheckable.class +SHA1-Digest: rK9QVEZwEdCcusxW3jPnhyKP69s= + +Name: org/eclipse/jface/action/IMenuListener.class +SHA1-Digest: XGLegWw7uJyNCBFMeqhJqeFQq80= + +Name: org/eclipse/jface/dialogs/IDialogConstants.class +SHA1-Digest: F6Q5E9oHkyGl+kdTgOQwIut4YI0= + +Name: org/eclipse/jface/operation/AccumulatingProgressMonitor$3.class +SHA1-Digest: /W3tELlqeYoDMeqi5OpIcwy25oE= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProp + osalPopup.class +SHA1-Digest: lR99G8CxSJNu7IU+AQfOo/qzgMs= + +Name: org/eclipse/jface/util/Assert.class +SHA1-Digest: XdV7j5TiXZEMFmkgPoa/X0RuwVQ= + +Name: org/eclipse/jface/viewers/DialogCellEditor$DialogCellLayout.clas + s +SHA1-Digest: bk25CDJJL7PDwHtRjI35Ui6amOQ= + +Name: org/eclipse/jface/preference/PreferenceNode.class +SHA1-Digest: 6yml3aZl2p9SAdAPAoFHCNWTkQI= + +Name: org/eclipse/jface/action/Action.class +SHA1-Digest: YY+4PWn4Z1MGifXiRcvq3baYrFg= + +Name: org/eclipse/jface/util/SafeRunnableDialog$4.class +SHA1-Digest: UryJn0w04ssNX6KLS8Wz70PXRnY= + +Name: org/eclipse/jface/messages.properties +SHA1-Digest: 1AE74/GTrLZcH6PUlF4unDyg/r0= + +Name: org/eclipse/jface/dialogs/ControlEnableState.class +SHA1-Digest: bNJx0mD0lQAhKw4/eaWoSTXLFl0= + +Name: org/eclipse/jface/viewers/FocusCellHighlighter.class +SHA1-Digest: d6PtIB22jvo+o6to25JX8jSh1zY= + +Name: org/eclipse/jface/viewers/AbstractTreeViewer$3.class +SHA1-Digest: UeNqzpJXcRURKWgx+MpCSZxB03Q= + +Name: org/eclipse/jface/viewers/Viewer$1.class +SHA1-Digest: XZTuWaebhl1SRc3T3suK0pRBeYU= + +Name: org/eclipse/jface/action/ActionContributionItem$4.class +SHA1-Digest: vkPZOQLw+WeldJa9FdYnS3mIKWY= + +Name: org/eclipse/jface/internal/InternalPolicy.class +SHA1-Digest: 7/DN/MbxcrL2BY1KCJQSCHz9GZU= + +Name: org/eclipse/jface/fieldassist/images/errorqf_ovr.gif +SHA1-Digest: Um1Gp9X1ZLQQXPbSn55JPp4zdQE= + +Name: org/eclipse/jface/action/SubStatusLineManager.class +SHA1-Digest: HMQeBJgEcTGjW3WjkHEFGFY54BM= + +Name: org/eclipse/jface/bindings/keys/KeySequenceText$TraversalFilterM + anager.class +SHA1-Digest: rG7+caEfvMHcnLpB3P+bZcG+JG4= + +Name: org/eclipse/jface/preference/IntegerFieldEditor.class +SHA1-Digest: ZknSkGrFM+5x9rutNtf8J+J18tk= + +Name: org/eclipse/jface/viewers/StructuredViewer$7.class +SHA1-Digest: DfyzSlUVRhku5oAHcaimtTUsMmo= + +Name: org/eclipse/jface/util/DelegatingDropAdapter$6.class +SHA1-Digest: A6O4p4KCOLRlh+aOjcs6HpTY3Ks= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$14.class +SHA1-Digest: PYrRZRMj0hwbSK/zF3Uw/D70shI= + +Name: org/eclipse/jface/dialogs/TitleAreaDialog$1.class +SHA1-Digest: FNeyU+GHMHkrQAwXOVd+5P9nrQg= + +Name: org/eclipse/jface/viewers/Viewer.class +SHA1-Digest: gBkcQUZMqjjBaDHcl1WXyw4RCrY= + +Name: org/eclipse/jface/viewers/deferred/ChangeQueue$Change.class +SHA1-Digest: 9f/YGJeC/TD7LY8woROG6M1fDQE= + +Name: org/eclipse/jface/resource/ResourceManager.class +SHA1-Digest: Dyhj/QDC0ZdNmq0Qtt5rAU/6gw8= + +Name: org/eclipse/jface/action/StatusLineLayoutData.class +SHA1-Digest: T8HPa7xIJIIGPNT46SdWVSXArUE= + +Name: org/eclipse/jface/dialogs/PopupDialog$MoveAction.class +SHA1-Digest: thlMX+3p2Eez56ZbgmddcMXqX6s= + +Name: org/eclipse/jface/wizard/IWizardContainer.class +SHA1-Digest: t6UIOrVi+LgTyr6Ror/O1myGmc8= + +Name: org/eclipse/jface/viewers/TextCellEditor$3.class +SHA1-Digest: A6fAlBwC5yzeFeyV8+yhfbATxIM= + +Name: org/eclipse/jface/viewers/CustomHashtable$EmptyEnumerator.class +SHA1-Digest: iRTEprgJrq6KopjhMrYJO5yq0Nc= + +Name: org/eclipse/jface/preference/ComboFieldEditor.class +SHA1-Digest: VBXzKuE1En4dC8OU8EST0pAg3HU= + +Name: org/eclipse/jface/resource/jfacefonts_windows2000.properties +SHA1-Digest: fNufPvbgB1v0tuy/96aaa7Ox+Ds= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProp + osalPopup$PopupCloserListener.class +SHA1-Digest: 5rFpZ7aGwkim8B0mrZyrf41UxRc= + +Name: org/eclipse/jface/util/IPropertyChangeListener.class +SHA1-Digest: NsV5pgvLNCDRe6D77HTE5mbo9Zw= + +Name: org/eclipse/jface/action/ToolBarContributionItem$3.class +SHA1-Digest: u29QnAR7W4XJckBTZigBhlhe9Jo= + +Name: org/eclipse/jface/util/IOpenEventListener.class +SHA1-Digest: O1KuuU6LNLaw4ohBnG8tkPtOVx8= + +Name: org/eclipse/jface/util/DelegatingDropAdapter.class +SHA1-Digest: slrNm/O5OWcqB4nFYluqPlnknp8= + +Name: org/eclipse/jface/bindings/keys/KeySequence.class +SHA1-Digest: T/jhzNZ6gjUuFW17XnTggVHjnW4= + +Name: org/eclipse/jface/preference/JFacePreferences.class +SHA1-Digest: j1Yen4upKix72kc4gM+8V+IT+mQ= + +Name: org/eclipse/jface/viewers/TreeNode.class +SHA1-Digest: pWqn3M1KVaIrkF19WJZJaYd9cx8= + +Name: org/eclipse/jface/internal/provisional/action/IToolBarContributi + onItem.class +SHA1-Digest: T28GsgkyXThg7Sqi9/guUy3WaCA= + +Name: org/eclipse/jface/viewers/TextCellEditor.class +SHA1-Digest: I/qrH7ONV70oN00F/mD9gLuwUM8= + +Name: org/eclipse/jface/dialogs/ProgressMonitorDialog$2.class +SHA1-Digest: A/1jXUaO26kKR0gcJ676cEmeDWc= + +Name: org/eclipse/jface/wizard/WizardPage.class +SHA1-Digest: 8vTb/Mu1p3w48VRMvf7bS9uVtd0= + +Name: org/eclipse/jface/window/Window$2.class +SHA1-Digest: gn5QsegN1dmrC9AfR+XyR7WryA0= + +Name: org/eclipse/jface/resource/jfacefonts_linux.properties +SHA1-Digest: MPIe46ddE+PVndulixs9MVOt9QM= + +Name: org/eclipse/jface/fieldassist/ControlDecoration$Hover.class +SHA1-Digest: BvM9VBU+lBCxadpvtyYFvpodkqs= + +Name: org/eclipse/jface/dialogs/images/message_warning.gif +SHA1-Digest: NTU6oN3RVw9xXNgd8iqw6yXxmws= + +Name: org/eclipse/jface/commands/RadioState$RadioStateManager.class +SHA1-Digest: 4pf9kmlMExF4NuTbbxwYasNwjxI= + +Name: org/eclipse/jface/resource/DerivedImageDescriptor.class +SHA1-Digest: Z3WfSlMbycShUorbqWYWrcKnAhE= + +Name: org/eclipse/jface/fieldassist/IControlCreator.class +SHA1-Digest: bBaZd6FmLuWnd3IBehnFDoQS4So= + +Name: org/eclipse/jface/viewers/DecorationOverlayIcon.class +SHA1-Digest: Y7UN+ZBMslqOwChKuTP+JVbvOCY= + +Name: org/eclipse/jface/preference/FontFieldEditor$4.class +SHA1-Digest: HOPmvZNPfrdPFIdmb2koHIfQVA0= + +Name: org/eclipse/jface/viewers/TableLayout.class +SHA1-Digest: zPCs8XBBMr0ffICbyPASqKq7Uyw= + +Name: org/eclipse/jface/viewers/deferred/ConcurrentTableUpdator.class +SHA1-Digest: OwzjHLLd/DTQ7zD5MYsfBSZYtLs= + +Name: org/eclipse/jface/viewers/ColumnViewerEditor$4.class +SHA1-Digest: 46oxUsLbLTUc8QXl4t6S8Sd+/20= + +Name: org/eclipse/jface/window/ToolTip$3.class +SHA1-Digest: Or+4UVtfOW2WSAYqLhNwF34+jlE= + +Name: org/eclipse/jface/preference/StringFieldEditor$3.class +SHA1-Digest: Z2Tzj8/yEyrrbi1uk/RnOOGx5Os= + +Name: org/eclipse/jface/fieldassist/FieldAssistColors.class +SHA1-Digest: 6O3TNVYciymrfLYWCrbX1TopUUY= + +Name: org/eclipse/jface/viewers/ISelection.class +SHA1-Digest: v6qu+ZFiiJ/B7ag5Te3pBK19BHQ= + +Name: org/eclipse/jface/viewers/TreePath.class +SHA1-Digest: qM2oISuX8yH+BaKH7B4KZNWfUVU= + +Name: org/eclipse/jface/viewers/TreeViewer$5.class +SHA1-Digest: Isq93suZbPTe+8u6BYsK6J9rZ5E= + +Name: org/eclipse/jface/viewers/IElementComparer.class +SHA1-Digest: sOaZtvS4AB/hqgZ5D1RIsBJ6lyI= + +Name: org/eclipse/jface/layout/TreeColumnLayout.class +SHA1-Digest: x+0oz+CX28DxveiHNLcH8z2PSp8= + +Name: org/eclipse/jface/action/SubContributionManager$1.class +SHA1-Digest: y2osOkOKwIUm8er1pBR708XDBHQ= + +Name: org/eclipse/jface/viewers/ColumnViewerEditorActivationListener.c + lass +SHA1-Digest: bZzW8WEagCO4g5LGt7gAdKv4fok= + +Name: org/eclipse/jface/window/DefaultToolTip.class +SHA1-Digest: vWYCKbbRk7vky9sv4+XyuNzoBsM= + +Name: org/eclipse/jface/util/Geometry.class +SHA1-Digest: NOSckiiUmNQhIY4uV5Wdzgt7Pl8= + +Name: org/eclipse/jface/resource/DeviceResourceManager.class +SHA1-Digest: K0fl0ke6tO8VbENziK6aQ3L60Ok= + +Name: org/eclipse/jface/preference/PreferenceDialog$PageLayout.class +SHA1-Digest: hgPfD3IdU0KAPdn/+v+qs+JNL7k= + +Name: org/eclipse/jface/action/ExternalActionManager$IBindingManagerCa + llback.class +SHA1-Digest: ltqW2wL1ugLf4e22Vauu7bLzGNI= + +Name: org/eclipse/jface/viewers/DialogCellEditor.class +SHA1-Digest: H6RNBVJwdHT0CD1AvM1h49Pgjpk= + +Name: org/eclipse/jface/window/ToolTip$ToolTipOwnerControlListener.cla + ss +SHA1-Digest: raTdFjdhKwG5kUAmMvx7frBvQ/c= + +Name: org/eclipse/jface/action/SubContributionManager.class +SHA1-Digest: U5W16vpvNvo4s2TZxiaOxJEnRLY= + +Name: org/eclipse/jface/viewers/StructuredViewer$2.class +SHA1-Digest: ULFmm/2x5DVLM76TmWuN/KHgJeM= + +Name: org/eclipse/jface/viewers/deferred/ChangeQueue.class +SHA1-Digest: q7v2iwDl52cXjFX5aGC50Su/qtY= + +Name: org/eclipse/jface/fieldassist/DecoratedField$3.class +SHA1-Digest: HopONxRvINGg5HdPKEvjSYTJQsk= + +Name: org/eclipse/jface/fieldassist/ControlDecoration$7.class +SHA1-Digest: vw4W7AHZA8HlQmkK1QZH2kzNR9Q= + +Name: org/eclipse/jface/util/DelegatingDropAdapter$1.class +SHA1-Digest: YTc8uaLSnGz/1kS97jxUqoLU5Z8= + +Name: org/eclipse/jface/viewers/ViewerLabel.class +SHA1-Digest: RmWs07S4iNrcxmk/9vOwwJT0u1A= + +Name: org/eclipse/jface/bindings/keys/formatting/EmacsKeyFormatter.pro + perties +SHA1-Digest: f2Wrkiulg1IixjoSP3f/We7gLlk= + +Name: org/eclipse/jface/resource/jfacefonts_windowsxp.properties +SHA1-Digest: AOq+tOEd4D7kDs1EriU8ejSUBw0= + +Name: org/eclipse/jface/preference/RadioGroupFieldEditor$1.class +SHA1-Digest: Ht+NUxZq1ltSesaqW4c5lPo97FM= + +Name: org/eclipse/jface/preference/ScaleFieldEditor.class +SHA1-Digest: ebMXK9FL5rhpK0uhuPPsxf8V0PA= + +Name: org/eclipse/jface/fieldassist/images/info_ovr.gif +SHA1-Digest: QOIr94zJdt1aM96T1ySsGB2diq0= + +Name: org/eclipse/jface/dialogs/Dialog$2.class +SHA1-Digest: t1PEV5jkUDjpT+vZEIyNQ+D/t6k= + +Name: org/eclipse/jface/bindings/Trigger.class +SHA1-Digest: ScMIxH6pA8H2s/qpnZ4RStKqm4A= + +Name: org/eclipse/jface/preference/PreferenceDialog$9.class +SHA1-Digest: 9CysviQ86AJCcrzyR3RsHVNtdLo= + +Name: org/eclipse/jface/action/StatusLine$1.class +SHA1-Digest: 1eNlUkuGlgioHpas3+yLSCNIKwY= + +Name: org/eclipse/jface/dialogs/ErrorDialog.class +SHA1-Digest: enTlYXi3qDaY12njhet+QCoewqc= + +Name: org/eclipse/jface/viewers/ColumnViewer.class +SHA1-Digest: 1lrwGiVxUTZvXpYovewE8JppR50= + +Name: org/eclipse/jface/layout/GridDataFactory.class +SHA1-Digest: ZNJ6USDgac1ey4OzFI3Nq1YEmW0= + +Name: org/eclipse/jface/dialogs/IPageChangedListener.class +SHA1-Digest: 8B3Te8gqEOgUJWN6ZTxIpy+Vfu8= + +Name: org/eclipse/jface/wizard/WizardDialog$5.class +SHA1-Digest: bD3ABgsmJGNBiIQoJm7/hkm834I= + +Name: org/eclipse/jface/preference/PreferenceDialog$14.class +SHA1-Digest: 32dZRx1+iJRASSKriotmgOQdURc= + +Name: org/eclipse/jface/viewers/TreePathViewerSorter.class +SHA1-Digest: T+cz5sTsuNx8icLNrEIwlt2QOj4= + +Name: org/eclipse/jface/viewers/CellEditor$4.class +SHA1-Digest: dFe4RhMEFxg4EY5y9W3Z+/loc8g= + +Name: org/eclipse/jface/dialogs/PopupDialog$4.class +SHA1-Digest: +xnp7OGFdUnmUUM/AWMp2p8ly68= + +Name: org/eclipse/jface/dialogs/AnimatorFactory.class +SHA1-Digest: YCT0EGjeUbg8jYcm8shnbDGsW8Q= + +Name: org/eclipse/jface/viewers/ComboBoxCellEditor$3.class +SHA1-Digest: vkM9PvZ4rF9F/wo2GzgYzOYydH4= + +Name: org/eclipse/jface/viewers/OwnerDrawLabelProvider$1.class +SHA1-Digest: rXBeIfEAbZt/agUC5qCogBQT1As= + +Name: org/eclipse/jface/viewers/ICellEditorValidator.class +SHA1-Digest: ghG+8bfz08dZdRU29KWTaHI/Rjw= + +Name: org/eclipse/jface/bindings/keys/KeyStroke.class +SHA1-Digest: xcTPBRotDFWyjD8BNgymKE2gS+Y= + +Name: org/eclipse/jface/bindings/keys/KeyBinding.class +SHA1-Digest: kwvTdtSvRi+QnHqhh4fmIlZIyGE= + +Name: org/eclipse/jface/fieldassist/FieldAssistColors$1.class +SHA1-Digest: TXyAp8d6WU00E1wJMO2BeGAa/Ck= + +Name: org/eclipse/jface/dialogs/ErrorSupportProvider.class +SHA1-Digest: gvaYXsWvVx/66U1KDxG7mZv9TV4= + +Name: org/eclipse/jface/dialogs/MessageDialogWithToggle$1.class +SHA1-Digest: OcOo7ww80O+jNlWfO8kJSoX/bmY= + +Name: org/eclipse/jface/viewers/DecorationContext.class +SHA1-Digest: hGnn7RBTdKb3jxicuGW5ioH3rQk= + +Name: org/eclipse/jface/viewers/ComboBoxCellEditor.class +SHA1-Digest: kgR5uSqCR6xLG6o46EDT5PxLadY= + +Name: org/eclipse/jface/resource/JFaceResources$1.class +SHA1-Digest: Dj7mbHmRa6ff5Plfw8Vr7qPnUB8= + +Name: org/eclipse/jface/viewers/AbstractTableViewer$VirtualManager.cla + ss +SHA1-Digest: VsUK9MANZr6j1KV9du+/kmE9pis= + +Name: org/eclipse/jface/preference/IPreferenceNode.class +SHA1-Digest: 8tRoUpdBxtXH37yYHrB0B0E8mkY= + +Name: org/eclipse/jface/dialogs/TrayDialog$4.class +SHA1-Digest: 8RyiTidCFwaxF0gH+BJ7WEdVJ7U= + +Name: org/eclipse/jface/action/images/stop.gif +SHA1-Digest: BPcRKHh123ukCk1ZIcRxysDWb3Y= + +Name: org/eclipse/jface/viewers/TreeExpansionEvent.class +SHA1-Digest: dxgpuR+QbjaE0xBNYuiCaOBkB0o= + +Name: org/eclipse/jface/dialogs/IDialogPage.class +SHA1-Digest: rBVidzUUL1Qu/Ro2KSkJ16brX0A= + +Name: org/eclipse/jface/bindings/keys/formatting/IKeyFormatter.class +SHA1-Digest: Uy80BmGwT0KCWMkZ1gdTijPn77A= + +Name: org/eclipse/jface/util/OpenStrategy$3.class +SHA1-Digest: q+71OFHnpsmqfZwQpr+lveNVKeE= + +Name: org/eclipse/jface/fieldassist/ContentProposalAdapter$6.class +SHA1-Digest: 6m+z82N0vDfXlV496kFa6qa8FIg= + +Name: org/eclipse/jface/viewers/ColumnViewerToolTipSupport.class +SHA1-Digest: dYhZ6C6DNlIasK5ii//RWXk7FT4= + +Name: org/eclipse/jface/preference/StringButtonFieldEditor$2.class +SHA1-Digest: so+QwMmBgkGvU/GbGvFaZe1wA9o= + +Name: org/eclipse/jface/window/WindowManager.class +SHA1-Digest: Ti8XgX1pgBG7tLPHFVKPA4WcpRo= + +Name: org/eclipse/jface/resource/jfacefonts_qnx.properties +SHA1-Digest: 1XnKDbwb/W15J/0x9HL752KjFIA= + +Name: org/eclipse/jface/viewers/deferred/LazySortedCollection.class +SHA1-Digest: 6NhclZEGF0+Rs69muBm13BJXTMw= + diff --git a/Annotation/META-INF/MANIFEST.MF b/Annotation/META-INF/MANIFEST.MF new file mode 100644 index 0000000..3a4ab9d --- /dev/null +++ b/Annotation/META-INF/MANIFEST.MF @@ -0,0 +1,4 @@ +Manifest-Version: 1.0 +Ant-Version: Apache Ant 1.7.1 +Created-By: 10.0-b23 (Sun Microsystems Inc.) + diff --git a/Annotation/META-INF/eclipse.inf b/Annotation/META-INF/eclipse.inf new file mode 100644 index 0000000..7864d3c --- /dev/null +++ b/Annotation/META-INF/eclipse.inf @@ -0,0 +1,3 @@ +#Processed using Jarprocessor +pack200.args = -E4 +pack200.conditioned = true diff --git a/Annotation/about.html b/Annotation/about.html new file mode 100644 index 0000000..4602330 --- /dev/null +++ b/Annotation/about.html @@ -0,0 +1,28 @@ + + + + +About + + +

About This Content

+ +

June 2, 2006

+

License

+ +

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at http://www.eclipse.org/legal/epl-v10.html. +For purposes of the EPL, "Program" will mean the Content.

+ +

If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at http://www.eclipse.org.

+ + + \ No newline at end of file diff --git a/Annotation/external.xpt b/Annotation/external.xpt new file mode 100644 index 0000000..f57da7e Binary files /dev/null and b/Annotation/external.xpt differ diff --git a/Annotation/plugin.properties b/Annotation/plugin.properties new file mode 100644 index 0000000..528303e --- /dev/null +++ b/Annotation/plugin.properties @@ -0,0 +1,12 @@ +############################################################################### +# Copyright (c) 2000, 2005 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +pluginName = JFace +providerName = Eclipse.org diff --git a/Annotation/plugins/BPTPlugin.plugin/bptplugin.jar b/Annotation/plugins/BPTPlugin.plugin/bptplugin.jar new file mode 100644 index 0000000..d4025cf Binary files /dev/null and b/Annotation/plugins/BPTPlugin.plugin/bptplugin.jar differ diff --git a/Annotation/plugins/BPTPlugin.plugin/jbpt.dll b/Annotation/plugins/BPTPlugin.plugin/jbpt.dll new file mode 100644 index 0000000..d12f777 Binary files /dev/null and b/Annotation/plugins/BPTPlugin.plugin/jbpt.dll differ diff --git a/Annotation/plugins/BPTPlugin.plugin/libjbpt.jnilib b/Annotation/plugins/BPTPlugin.plugin/libjbpt.jnilib new file mode 100644 index 0000000..77039d7 Binary files /dev/null and b/Annotation/plugins/BPTPlugin.plugin/libjbpt.jnilib differ diff --git a/Annotation/plugins/BPTPlugin.plugin/libjbpt.so b/Annotation/plugins/BPTPlugin.plugin/libjbpt.so new file mode 100644 index 0000000..5b69c7d Binary files /dev/null and b/Annotation/plugins/BPTPlugin.plugin/libjbpt.so differ diff --git a/Annotation/plugins/BPTPlugin.plugin/libjbpt64.so b/Annotation/plugins/BPTPlugin.plugin/libjbpt64.so new file mode 100644 index 0000000..998a3d4 Binary files /dev/null and b/Annotation/plugins/BPTPlugin.plugin/libjbpt64.so differ diff --git a/Annotation/plugins/BPTPlugin.plugin/plugin.xml b/Annotation/plugins/BPTPlugin.plugin/plugin.xml new file mode 100644 index 0000000..4ae529d --- /dev/null +++ b/Annotation/plugins/BPTPlugin.plugin/plugin.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Annotation/plugins/IGCPlugin.plugin/igcplugin.jar b/Annotation/plugins/IGCPlugin.plugin/igcplugin.jar new file mode 100644 index 0000000..c85393b Binary files /dev/null and b/Annotation/plugins/IGCPlugin.plugin/igcplugin.jar differ diff --git a/Annotation/plugins/IGCPlugin.plugin/jigc.dll b/Annotation/plugins/IGCPlugin.plugin/jigc.dll new file mode 100644 index 0000000..b4ee98c Binary files /dev/null and b/Annotation/plugins/IGCPlugin.plugin/jigc.dll differ diff --git a/Annotation/plugins/IGCPlugin.plugin/libjigc.jnilib b/Annotation/plugins/IGCPlugin.plugin/libjigc.jnilib new file mode 100644 index 0000000..6ff9817 Binary files /dev/null and b/Annotation/plugins/IGCPlugin.plugin/libjigc.jnilib differ diff --git a/Annotation/plugins/IGCPlugin.plugin/libjigc.so b/Annotation/plugins/IGCPlugin.plugin/libjigc.so new file mode 100644 index 0000000..926f242 Binary files /dev/null and b/Annotation/plugins/IGCPlugin.plugin/libjigc.so differ diff --git a/Annotation/plugins/IGCPlugin.plugin/libjigc64.so b/Annotation/plugins/IGCPlugin.plugin/libjigc64.so new file mode 100644 index 0000000..e7a71b3 Binary files /dev/null and b/Annotation/plugins/IGCPlugin.plugin/libjigc64.so differ diff --git a/Annotation/plugins/IGCPlugin.plugin/plugin.xml b/Annotation/plugins/IGCPlugin.plugin/plugin.xml new file mode 100644 index 0000000..2b7ae2e --- /dev/null +++ b/Annotation/plugins/IGCPlugin.plugin/plugin.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Annotation/plugins/SIOXPlugin.plugin/plugin.xml b/Annotation/plugins/SIOXPlugin.plugin/plugin.xml new file mode 100644 index 0000000..623ad7b --- /dev/null +++ b/Annotation/plugins/SIOXPlugin.plugin/plugin.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Annotation/plugins/SIOXPlugin.plugin/sioxapi.jar b/Annotation/plugins/SIOXPlugin.plugin/sioxapi.jar new file mode 100644 index 0000000..4c121b2 Binary files /dev/null and b/Annotation/plugins/SIOXPlugin.plugin/sioxapi.jar differ diff --git a/Annotation/plugins/SIOXPlugin.plugin/sioxplugin.jar b/Annotation/plugins/SIOXPlugin.plugin/sioxplugin.jar new file mode 100644 index 0000000..31f959a Binary files /dev/null and b/Annotation/plugins/SIOXPlugin.plugin/sioxplugin.jar differ diff --git a/Annotation/plugins/SRGPlugin.plugin/jsrg.dll b/Annotation/plugins/SRGPlugin.plugin/jsrg.dll new file mode 100644 index 0000000..c381fae Binary files /dev/null and b/Annotation/plugins/SRGPlugin.plugin/jsrg.dll differ diff --git a/Annotation/plugins/SRGPlugin.plugin/libjsrg.jnilib b/Annotation/plugins/SRGPlugin.plugin/libjsrg.jnilib new file mode 100644 index 0000000..46427e8 Binary files /dev/null and b/Annotation/plugins/SRGPlugin.plugin/libjsrg.jnilib differ diff --git a/Annotation/plugins/SRGPlugin.plugin/libjsrg.so b/Annotation/plugins/SRGPlugin.plugin/libjsrg.so new file mode 100644 index 0000000..c44f5af Binary files /dev/null and b/Annotation/plugins/SRGPlugin.plugin/libjsrg.so differ diff --git a/Annotation/plugins/SRGPlugin.plugin/libjsrg64.so b/Annotation/plugins/SRGPlugin.plugin/libjsrg64.so new file mode 100644 index 0000000..65cb9f7 Binary files /dev/null and b/Annotation/plugins/SRGPlugin.plugin/libjsrg64.so differ diff --git a/Annotation/plugins/SRGPlugin.plugin/plugin.xml b/Annotation/plugins/SRGPlugin.plugin/plugin.xml new file mode 100644 index 0000000..4061f98 --- /dev/null +++ b/Annotation/plugins/SRGPlugin.plugin/plugin.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Annotation/plugins/SRGPlugin.plugin/srgplugin.jar b/Annotation/plugins/SRGPlugin.plugin/srgplugin.jar new file mode 100644 index 0000000..c888c62 Binary files /dev/null and b/Annotation/plugins/SRGPlugin.plugin/srgplugin.jar differ diff --git a/Annotation/resources/ant/lib/ant-deb.jar b/Annotation/resources/ant/lib/ant-deb.jar new file mode 100644 index 0000000..f602bec Binary files /dev/null and b/Annotation/resources/ant/lib/ant-deb.jar differ diff --git a/Annotation/resources/ant/lib/ant-gzip2.jar b/Annotation/resources/ant/lib/ant-gzip2.jar new file mode 100644 index 0000000..271f123 Binary files /dev/null and b/Annotation/resources/ant/lib/ant-gzip2.jar differ diff --git a/Annotation/resources/ant/lib/ant-passwd-task.jar b/Annotation/resources/ant/lib/ant-passwd-task.jar new file mode 100644 index 0000000..b4f4b76 Binary files /dev/null and b/Annotation/resources/ant/lib/ant-passwd-task.jar differ diff --git a/Annotation/resources/ant/lib/ant-swt-identify.jar b/Annotation/resources/ant/lib/ant-swt-identify.jar new file mode 100644 index 0000000..daddc1c Binary files /dev/null and b/Annotation/resources/ant/lib/ant-swt-identify.jar differ diff --git a/Annotation/resources/ant/lib/jsmoothgen-ant.jar b/Annotation/resources/ant/lib/jsmoothgen-ant.jar new file mode 100644 index 0000000..c9e283d Binary files /dev/null and b/Annotation/resources/ant/lib/jsmoothgen-ant.jar differ diff --git a/Annotation/resources/ant/lib/standalone-compiler.jar b/Annotation/resources/ant/lib/standalone-compiler.jar new file mode 100644 index 0000000..2762975 Binary files /dev/null and b/Annotation/resources/ant/lib/standalone-compiler.jar differ diff --git a/Annotation/resources/ant/properties b/Annotation/resources/ant/properties new file mode 100644 index 0000000..38b429c --- /dev/null +++ b/Annotation/resources/ant/properties @@ -0,0 +1,14 @@ +app.name=Interactive Segmentation Tool +app.package=ist +app.version=1.3.4 +app.author=Kevin McGuinness +app.email=kevin.mcguinness@eeng.dcu.ie +app.website=http://kspace.cdvp.dcu.ie/public/interactive-segmentation +app.synopsis=The CDVP Interactive Segmentation Tool +app.main=ie.dcu.apps.ist.Main + +# Compilation properties +java.debug=off +java.source.version=1.5 +java.target.version=1.5 + diff --git a/Annotation/resources/config/actions.mac.properties b/Annotation/resources/config/actions.mac.properties new file mode 100644 index 0000000..8a282fa --- /dev/null +++ b/Annotation/resources/config/actions.mac.properties @@ -0,0 +1,108 @@ + +OpenAction.dialog.text=Open an image or saved context +OpenAction.dialog.filter.exts=*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.ctx +OpenAction.dialog.filter.text=Image and Context Files + +SaveAction.dialog.text=Save Segmentation Context +SaveAction.dialog.filter.exts=*.ctx +SaveAction.dialog.filter.text=Segmentation Context Files + +ExportViewAction.dialog.text=Export View As Image +ExportViewAction.dialog.filter.exts=*.jpg;*.jpeg;*.png;*.gif;*.bmp; +ExportViewAction.dialog.filter.text=Image Files + +OpenExperimentAction.dialog.text=Open an experiment file +OpenExperimentAction.dialog.filter.exts=*.exp +OpenExperimentAction.dialog.filter.text=Experiment Files + +# Actions +action.OpenAction.text=&Open...@Command+O +action.OpenAction.image=file:resources/icons/open.png +action.OpenAction.tooltip=Open image + +action.SaveAction.text=&Save@Command+S +action.SaveAction.image=file:resources/icons/save.png +action.SaveAction.tooltip=Save segmentation context + +action.SaveAsAction.text=S&ave As...@Command+Shift+S +action.SaveAsAction.image=file:resources/icons/save-as.png +action.SaveAsAction.tooltip=Save segmentation context as... + +action.ExportViewAction.text=&Current View...@Command+Alt+V +action.ExportViewAction.image=file:resources/icons/image.png +action.ExportViewAction.tooltip=Export view as image + +action.ExportImageMapAction.text=&HTML Image Map...@Command+Alt+H +action.ExportImageMapAction.image=file:resources/icons/html.png +action.ExportImageMapAction.tooltip=Export objects as HTML image map + +action.ExportTransparentPNGAction.text=Export Transparent &PNG...@Command+Alt+P +action.ExportTransparentPNGAction.image=file:resources/icons/image.png +action.ExportTransparentPNGAction.tooltip=Export a PNG of the current segmentation with a transparent background + +action.ImportAction.text=&Import... +action.ImportAction.image=file:resources/icons/import.png +action.ImportAction.tooltip=Import images + +action.PrintAction.text=&Print@Command+P +action.PrintAction.image=file:resources/icons/print.png +action.PrintAction.tooltip=Print view + +action.ExitAction.text=E&xit@Command+Q +action.ExitAction.image=file:resources/icons/exit.png +action.ExitAction.tooltip=Quit the application + +action.UndoAction.text=&Undo@Command+Z +action.UndoAction.image=file:resources/icons/undo.png +action.UndoAction.tooltip=Undo last markup + +action.RedoAction.text=&Redo@Command+Y +action.RedoAction.image=file:resources/icons/redo.png +action.RedoAction.tooltip=Redo markup + +action.CopyAction.text=&Copy@Command+C +action.CopyAction.image=file:resources/icons/copy.png +action.CopyAction.tooltip=Copy view to clipboard as image + +action.PreferencesAction.text=&Preferences...@Command+, +action.PreferencesAction.image=file:resources/icons/preferences.png +action.PreferencesAction.tooltip=Change application settings + +action.AddFilesAction.text=&Add Files...@Command+A +action.AddFilesAction.image=file:resources/icons/add.png +action.AddFilesAction.tooltip=Add image files to project + +action.RemoveFilesAction.text=&Remove Files@Command+R +action.RemoveFilesAction.image=file:resources/icons/remove.png +action.RemoveFilesAction.tooltip=Remove selected image files from project + +action.PreviousAction.text=&Previous@Command+[ +action.PreviousAction.image=file:resources/icons/previous.png +action.PreviousAction.tooltip=Move to previous image in directory + +action.NextAction.text=&Next@Command+] +action.NextAction.image=file:resources/icons/next.png +action.NextAction.tooltip=Move to next image in directory + +action.HelpAction.text=&Help Contents...@Command+F1 +action.HelpAction.image=file:resources/icons/help.png +action.HelpAction.tooltip=Show application help browser +action.HelpAction.helpURL=http://kspace.cdvp.dcu.ie/public/interactive-segmentation/doc/help.html + +action.AboutAction.text=&About... +action.AboutAction.image=file:resources/icons/about.png +action.AboutAction.tooltip=About the application +action.AboutAction.aboutImage=file:resources/icons/about-box.png + +action.OpenExperimentAction.text=Open &Experiment... +action.OpenExperimentAction.image=file:resources/icons/experiment.png +action.OpenExperimentAction.tooltip=Open an experiment file and switch to experiment mode + +action.ConfigureSegmenterAction.text=&Configure Segmenter...@Command+Shift+C +action.ConfigureSegmenterAction.image=file:resources/icons/preferences.png +action.ConfigureSegmenterAction.tooltip=Configure segmenter parameters + +action.SelectSegmenterAction.NA=Algorithm not available on this platform + + + diff --git a/Annotation/resources/config/actions.properties b/Annotation/resources/config/actions.properties new file mode 100644 index 0000000..f2ddcb0 --- /dev/null +++ b/Annotation/resources/config/actions.properties @@ -0,0 +1,106 @@ + +OpenAction.dialog.text=Open an image or saved context +OpenAction.dialog.filter.exts=*.jpg;*.jpeg;*.png;*.gif;*.bmp;*.ctx +OpenAction.dialog.filter.text=Image and Context Files + +SaveAction.dialog.text=Save Segmentation Context +SaveAction.dialog.filter.exts=*.ctx +SaveAction.dialog.filter.text=Segmentation Context Files + +ExportViewAction.dialog.text=Export View As Image +ExportViewAction.dialog.filter.exts=*.jpg;*.jpeg;*.png;*.gif;*.bmp; +ExportViewAction.dialog.filter.text=Image Files + +OpenExperimentAction.dialog.text=Open an experiment file +OpenExperimentAction.dialog.filter.exts=*.exp +OpenExperimentAction.dialog.filter.text=Experiment Files + +# Actions +action.OpenAction.text=&Open...@Ctrl+O +action.OpenAction.image=file:resources/icons/open.png +action.OpenAction.tooltip=Open image + +action.SaveAction.text=&Save@Ctrl+S +action.SaveAction.image=file:resources/icons/save.png +action.SaveAction.tooltip=Save segmentation context + +action.SaveAsAction.text=S&ave As...@Ctrl+Shift+S +action.SaveAsAction.image=file:resources/icons/save-as.png +action.SaveAsAction.tooltip=Save segmentation context as... + +action.ExportViewAction.text=&Current View...@Ctrl+Shift+V +action.ExportViewAction.image=file:resources/icons/image.png +action.ExportViewAction.tooltip=Export view as image + +action.ExportImageMapAction.text=&HTML Image Map...@Ctrl+Shift+H +action.ExportImageMapAction.image=file:resources/icons/html.png +action.ExportImageMapAction.tooltip=Export objects as HTML image map + +action.ExportTransparentPNGAction.text=Export Transparent &PNG...@Ctrl+Shift+P +action.ExportTransparentPNGAction.image=file:resources/icons/image.png +action.ExportTransparentPNGAction.tooltip=Export a PNG of the current segmentation with a transparent background + + +action.ImportAction.text=&Import... +action.ImportAction.image=file:resources/icons/import.png +action.ImportAction.tooltip=Import images + +action.PrintAction.text=&Print@Ctrl+P +action.PrintAction.image=file:resources/icons/print.png +action.PrintAction.tooltip=Print view + +action.ExitAction.text=E&xit@Ctrl+Q +action.ExitAction.image=file:resources/icons/exit.png +action.ExitAction.tooltip=Quit the application + +action.UndoAction.text=&Undo@Ctrl+Z +action.UndoAction.image=file:resources/icons/undo.png +action.UndoAction.tooltip=Undo last markup + +action.RedoAction.text=&Redo@Ctrl+Y +action.RedoAction.image=file:resources/icons/redo.png +action.RedoAction.tooltip=Redo markup + +action.CopyAction.text=&Copy@Ctrl+C +action.CopyAction.image=file:resources/icons/copy.png +action.CopyAction.tooltip=Copy view to clipboard as image + +action.PreferencesAction.text=&Preferences... +action.PreferencesAction.image=file:resources/icons/preferences.png +action.PreferencesAction.tooltip=Change application settings + +action.AddFilesAction.text=&Add Files...@Ctrl+A +action.AddFilesAction.image=file:resources/icons/add.png +action.AddFilesAction.tooltip=Add image files to project + +action.RemoveFilesAction.text=&Remove Files@Ctrl+R +action.RemoveFilesAction.image=file:resources/icons/remove.png +action.RemoveFilesAction.tooltip=Remove selected image files from project + +action.PreviousAction.text=&Previous@Ctrl+[ +action.PreviousAction.image=file:resources/icons/previous.png +action.PreviousAction.tooltip=Move to previous image in directory + +action.NextAction.text=&Next@Ctrl+] +action.NextAction.image=file:resources/icons/next.png +action.NextAction.tooltip=Move to next image in directory + +action.HelpAction.text=&Help Contents...@Ctrl+F1 +action.HelpAction.image=file:resources/icons/help.png +action.HelpAction.tooltip=Show application help browser +action.HelpAction.helpURL=http://kspace.cdvp.dcu.ie/public/interactive-segmentation/doc/help.html + +action.AboutAction.text=&About... +action.AboutAction.image=file:resources/icons/about.png +action.AboutAction.tooltip=About the application +action.AboutAction.aboutImage=file:resources/icons/about-box.png + +action.OpenExperimentAction.text=Open &Experiment... +action.OpenExperimentAction.image=file:resources/icons/experiment.png +action.OpenExperimentAction.tooltip=Open an experiment file and switch to experiment mode + +action.ConfigureSegmenterAction.text=&Configure Segmenter...@Ctrl+Shift+C +action.ConfigureSegmenterAction.image=file:resources/icons/preferences.png +action.ConfigureSegmenterAction.tooltip=Configure segmenter parameters + +action.SelectSegmenterAction.NA=Algorithm not available on this platform diff --git a/Annotation/resources/config/application.mac.properties b/Annotation/resources/config/application.mac.properties new file mode 100644 index 0000000..096ea68 --- /dev/null +++ b/Annotation/resources/config/application.mac.properties @@ -0,0 +1,25 @@ + +AppRecentMenu.icon=file:resources/icons/open-recent.png +ExportMenu.icon=file:resources/icons/export.png + +# Preferences Dialog +PrefsDialog.title=Preferences +PrefsDialog.application=Application +PrefsDialog.status=Status Area +PrefsDialog.view=View Preferences +PrefsDialog.experiment=Experiment Mode +PrefsDialog.general.tab=General +PrefsDialog.close.text=&Close +PrefsDialog.reset.text=&Reset +PrefsDialog.enable-feedback.text=Show position and color in the status area +PrefsDialog.foreground-color.text=Foreground color for markup +PrefsDialog.background-color.text=Background color for markup +PrefsDialog.experiment-embedded.text=Show experiment panel embedded in main window +PrefsDialog.confirm-exit.text=Confirm exit when application is closed + +# Experiment Panel +ExperimentPanel.description.title=Task Description +ExperimentPanel.timeout-message=The time allocated for this task is up! +ExperimentPanel.experiment-complete-message=The experiment has been completed +ExperimentPanel.button.text.start=Start +ExperimentPanel.button.text.finish=Finish diff --git a/Annotation/resources/config/application.properties b/Annotation/resources/config/application.properties new file mode 100644 index 0000000..d21c608 --- /dev/null +++ b/Annotation/resources/config/application.properties @@ -0,0 +1,27 @@ + +AppRecentMenu.icon=file:resources/icons/open-recent.png +ExportMenu.icon=file:resources/icons/export.png + +# Preferences Dialog +PrefsDialog.title=Preferences +PrefsDialog.application=Application +PrefsDialog.status=Status Area +PrefsDialog.view=View Preferences +PrefsDialog.experiment=Experiment Mode +PrefsDialog.general.tab=General +PrefsDialog.close.text=&Close +PrefsDialog.close.icon=file:resources/icons/close.png +PrefsDialog.reset.text=&Reset +PrefsDialog.reset.icon=file:resources/icons/reset.png +PrefsDialog.enable-feedback.text=Show position and color in the status area +PrefsDialog.foreground-color.text=Foreground color for markup +PrefsDialog.background-color.text=Background color for markup +PrefsDialog.experiment-embedded.text=Show experiment panel embedded in main window +PrefsDialog.confirm-exit.text=Confirm exit when application is closed + +# Experiment Panel +ExperimentPanel.description.title=Task Description +ExperimentPanel.timeout-message=The time allocated for this task is up! +ExperimentPanel.experiment-complete-message=The experiment has been completed +ExperimentPanel.button.text.start=Start +ExperimentPanel.button.text.finish=Finish diff --git a/Annotation/resources/config/view.properties b/Annotation/resources/config/view.properties new file mode 100644 index 0000000..73be3a2 --- /dev/null +++ b/Annotation/resources/config/view.properties @@ -0,0 +1,49 @@ +SegmentationView.Action.Foreground.text=Markup Foreground +SegmentationView.Action.Foreground.tooltip=Markup Foreground Pixels +SegmentationView.Action.Foreground.image=file:resources/icons/foreground.png +SegmentationView.Action.Background.text=Markup Background +SegmentationView.Action.Background.tooltip=Markup Background Pixels +SegmentationView.Action.Background.image=file:resources/icons/background.png +SegmentationView.Action.ZoomIn.text=Zoom In +SegmentationView.Action.ZoomIn.tooltip=Zoom In +SegmentationView.Action.ZoomIn.image=file:resources/icons/zoom-in.png +SegmentationView.Action.ZoomOut.text=Zoom Out +SegmentationView.Action.ZoomOut.tooltip=Zoom Out +SegmentationView.Action.ZoomOut.image=file:resources/icons/zoom-out.png +SegmentationView.Action.ZoomOriginal.text=Zoom Original +SegmentationView.Action.ZoomOriginal.tooltip=Zoom to Original Size +SegmentationView.Action.ZoomOriginal.image=file:resources/icons/zoom-original.png +SegmentationView.Action.ZoomBestFit.text=Zoom Best Fit +SegmentationView.Action.ZoomBestFit.tooltip=Zoom to Best Fit +SegmentationView.Action.ZoomBestFit.image=file:resources/icons/zoom-best-fit.png +SegmentationView.Action.Repaint.text=Refresh +SegmentationView.Action.Repaint.tooltip=Refresh and repaint view +SegmentationView.Action.Repaint.image=file:resources/icons/refresh.png +SegmentationView.Action.Undo.text=&Undo@Ctrl+Z +SegmentationView.Action.Undo.tooltip=Undo last markup +SegmentationView.Action.Undo.image=file:resources/icons/undo.png +SegmentationView.Action.Redo.text=&Redo@Ctrl+Y +SegmentationView.Action.Redo.tooltip=Redo markup +SegmentationView.Action.Redo.image=file:resources/icons/redo.png +SegmentationView.Action.Clear.text=&Clear@Ctrl+DELETE +SegmentationView.Action.Clear.tooltip=Clear all markup +SegmentationView.Action.Clear.image=file:resources/icons/clear.png +SegmentationView.Action.SetBrushSize.text=Set &Brush@Ctrl+B +SegmentationView.Action.SetBrushSize.tooltip=Set the markup brush size +SegmentationView.Action.SetBrushSize.image=file:resources/icons/brush.png +SegmentationView.Action.AutoApply.text=Auto Segment@Ctrl+Shift+A +SegmentationView.Action.AutoApply.tooltip=Toggle auto segment +SegmentationView.Action.AutoApply.image=file:resources/icons/auto.png +SegmentationView.Action.Apply.text=Segment@Ctrl+Shift+S +SegmentationView.Action.Apply.tooltip=Apply new markup now +SegmentationView.Action.Apply.image=file:resources/icons/apply.png +SegmentationView.Action.SetPainter.text=View : +SegmentationView.Action.SetPainter.tooltip=Select how to view the image/segmentation. +SegmentationView.Action.SetPainter.image= +SegmentationView.Action.SegmenterOptions.text=Configure Segmenter@Ctrl+Shift+C +SegmentationView.Action.SegmenterOptions.tooltip=Configure the segmenter +SegmentationView.Action.SegmenterOptions.image=file:resources/icons/preferences.png +SegmentationView.Action.SetLabel.text=Annotate : +SegmentationView.Action.SetLabel.tooltip=Annotate the segmented piece. +SegmentationView.Action.SetLabel.image= + diff --git a/Annotation/resources/doc/help.html b/Annotation/resources/doc/help.html new file mode 100644 index 0000000..44a573f --- /dev/null +++ b/Annotation/resources/doc/help.html @@ -0,0 +1,169 @@ + +Interactive Segmentation Tool - User Guide + +
+

Interactive Segmentation Tool

+

User Guide

+

Usage

+In this section I will outline how to perform typical operations using +the tool, such as opening images, extracting objects and exporting +segmentation masks.
+
+Open an Image 
+To open an image, select File->Open. Recently open files can +be accessed using the File->Open +Recent menu. Alternatively, an image file can be dragged +from your file system and dropped into the application to open it. +Currently images of type JPEG, PNG, GIF, and BMP are supported.
+
+Select a Segmenter
+There are several different segmenters available in the tool. These can +be selected from the Tools +menu. To select one, +click on it.
+
+Segmenting the Image 
+Once you have an image open and a segmenter selected, you can segment +the image by drawing scribbles on the image. First, move the mouse over +the object you want to extract. Left click and drag inside the object +to draw some scribbles inside the object. Now, move the mouse outside +the object to some background pixels. Using the right mouse button, +scribble outside the object to select some background. If using Mac +OSX, or if you do not have a right mouse button (Graphics Tablet etc), +you can use Ctrl +and click instead of right click.
+
+The image will be segmented and the foreground will be brightened and +the background darkened. If you are not happy with the segmentation, +you can add more foreground and background scribbles.
+
+Undo, Redo and Clear
+If you make a mistake, it can be undone by selecting Edit->Undo or +clicking the undo Undo Button button in the +toolbar. To redo, select Edit->Redo or click the +redo Redo Button button. To +remove all forground and background markup, click on the clear Clear Button button in the toolbar.
+
+Zooming
+To get a closer look at the image, the toolbar can also be +used to zoom-in on the image. To zoom-in by 10% use the Zoom In button. To zoom-out by 10% use +the Zoom Out button. To +zoom the image such that it fits into the window without needing +scrollbars, use the Zoom Best Fit +button. To restore the image to its original size use the Zoom Original button.
+
+Brush Size
+To change the brush size, use the Paintbrush button to show the brush size +chooser. It is often useful to use a bigger brush to make markings more +visible or to quickly mark up more pixels.
+
+Views
+It is sometimes useful to view the segmentation results in different +ways. The default selected view is called "Combined" and shows the +image, it's segmentation highlighted and the scribbles all overlayed on +the same image. By using the drop down menu, you can select a different +view:
+ +Note: +Only the combined view displays the foreground and +background markup (scribbles). So if you are wondering where the +scribbles disappeared to, select the combined view to make them visible.
+
+Saving and Exporting
+To save an work in progress segmentation, select File->Save or File->Save As. This +will save the current segmentation and markup as a context file (.ctx). When +finished segmenting an image, you may want to export the view as an +image. To export the current view select File->Export. +For example, if you wanted to save the segmentation mask, select the +mask view and then File->Export. +
+
+Configuring a Segmenter
+Some segmenters have parameters and options that can are configurable. +To configure the selected segmenter, select Tools->Configure +Segmenter, or click the Configure button in the toolbar.
+
+Navigating Directories of Images
+To quickly jump to the next or previous image in the current directory +(the one containing the open image), use the Go->Next and Go->Previous menu +items.
+
+Experiments
+Experiment files can be opened using the Tools->Open +Experiment menu item.


+ +
+ \ No newline at end of file diff --git a/Annotation/resources/icons/about-box.png b/Annotation/resources/icons/about-box.png new file mode 100644 index 0000000..3cd2db6 Binary files /dev/null and b/Annotation/resources/icons/about-box.png differ diff --git a/Annotation/resources/icons/about.png b/Annotation/resources/icons/about.png new file mode 100644 index 0000000..3b8a885 Binary files /dev/null and b/Annotation/resources/icons/about.png differ diff --git a/Annotation/resources/icons/application.png b/Annotation/resources/icons/application.png new file mode 100644 index 0000000..ca883da Binary files /dev/null and b/Annotation/resources/icons/application.png differ diff --git a/Annotation/resources/icons/apply.png b/Annotation/resources/icons/apply.png new file mode 100644 index 0000000..d7b5c2b Binary files /dev/null and b/Annotation/resources/icons/apply.png differ diff --git a/Annotation/resources/icons/auto.png b/Annotation/resources/icons/auto.png new file mode 100644 index 0000000..a3e8c31 Binary files /dev/null and b/Annotation/resources/icons/auto.png differ diff --git a/Annotation/resources/icons/background.png b/Annotation/resources/icons/background.png new file mode 100644 index 0000000..0e633a3 Binary files /dev/null and b/Annotation/resources/icons/background.png differ diff --git a/Annotation/resources/icons/brush.png b/Annotation/resources/icons/brush.png new file mode 100644 index 0000000..4bb955f Binary files /dev/null and b/Annotation/resources/icons/brush.png differ diff --git a/Annotation/resources/icons/clear.png b/Annotation/resources/icons/clear.png new file mode 100644 index 0000000..1556dfe Binary files /dev/null and b/Annotation/resources/icons/clear.png differ diff --git a/Annotation/resources/icons/close.png b/Annotation/resources/icons/close.png new file mode 100644 index 0000000..78b931f Binary files /dev/null and b/Annotation/resources/icons/close.png differ diff --git a/Annotation/resources/icons/copy.png b/Annotation/resources/icons/copy.png new file mode 100644 index 0000000..585579a Binary files /dev/null and b/Annotation/resources/icons/copy.png differ diff --git a/Annotation/resources/icons/dialog-error.png b/Annotation/resources/icons/dialog-error.png new file mode 100644 index 0000000..c2d0bb7 Binary files /dev/null and b/Annotation/resources/icons/dialog-error.png differ diff --git a/Annotation/resources/icons/dialog-information.png b/Annotation/resources/icons/dialog-information.png new file mode 100644 index 0000000..23824bb Binary files /dev/null and b/Annotation/resources/icons/dialog-information.png differ diff --git a/Annotation/resources/icons/dialog-warning.png b/Annotation/resources/icons/dialog-warning.png new file mode 100644 index 0000000..06148e8 Binary files /dev/null and b/Annotation/resources/icons/dialog-warning.png differ diff --git a/Annotation/resources/icons/exit.png b/Annotation/resources/icons/exit.png new file mode 100644 index 0000000..22a65a4 Binary files /dev/null and b/Annotation/resources/icons/exit.png differ diff --git a/Annotation/resources/icons/experiment.png b/Annotation/resources/icons/experiment.png new file mode 100644 index 0000000..cb16a60 Binary files /dev/null and b/Annotation/resources/icons/experiment.png differ diff --git a/Annotation/resources/icons/export.png b/Annotation/resources/icons/export.png new file mode 100644 index 0000000..f64425b Binary files /dev/null and b/Annotation/resources/icons/export.png differ diff --git a/Annotation/resources/icons/foreground.png b/Annotation/resources/icons/foreground.png new file mode 100644 index 0000000..4161f1d Binary files /dev/null and b/Annotation/resources/icons/foreground.png differ diff --git a/Annotation/resources/icons/help.png b/Annotation/resources/icons/help.png new file mode 100644 index 0000000..8542495 Binary files /dev/null and b/Annotation/resources/icons/help.png differ diff --git a/Annotation/resources/icons/html.png b/Annotation/resources/icons/html.png new file mode 100644 index 0000000..d95fcc0 Binary files /dev/null and b/Annotation/resources/icons/html.png differ diff --git a/Annotation/resources/icons/icon-16.png b/Annotation/resources/icons/icon-16.png new file mode 100644 index 0000000..b9e1264 Binary files /dev/null and b/Annotation/resources/icons/icon-16.png differ diff --git a/Annotation/resources/icons/icon-24.png b/Annotation/resources/icons/icon-24.png new file mode 100644 index 0000000..7b93ba1 Binary files /dev/null and b/Annotation/resources/icons/icon-24.png differ diff --git a/Annotation/resources/icons/icon-32.png b/Annotation/resources/icons/icon-32.png new file mode 100644 index 0000000..4bc8f32 Binary files /dev/null and b/Annotation/resources/icons/icon-32.png differ diff --git a/Annotation/resources/icons/icon-48.png b/Annotation/resources/icons/icon-48.png new file mode 100644 index 0000000..c3fca3e Binary files /dev/null and b/Annotation/resources/icons/icon-48.png differ diff --git a/Annotation/resources/icons/image.png b/Annotation/resources/icons/image.png new file mode 100644 index 0000000..247ccad Binary files /dev/null and b/Annotation/resources/icons/image.png differ diff --git a/Annotation/resources/icons/next.png b/Annotation/resources/icons/next.png new file mode 100644 index 0000000..0011e67 Binary files /dev/null and b/Annotation/resources/icons/next.png differ diff --git a/Annotation/resources/icons/open-recent.png b/Annotation/resources/icons/open-recent.png new file mode 100644 index 0000000..07cca3f Binary files /dev/null and b/Annotation/resources/icons/open-recent.png differ diff --git a/Annotation/resources/icons/open.png b/Annotation/resources/icons/open.png new file mode 100644 index 0000000..c3bcfcd Binary files /dev/null and b/Annotation/resources/icons/open.png differ diff --git a/Annotation/resources/icons/preferences.png b/Annotation/resources/icons/preferences.png new file mode 100644 index 0000000..e460eab Binary files /dev/null and b/Annotation/resources/icons/preferences.png differ diff --git a/Annotation/resources/icons/previous.png b/Annotation/resources/icons/previous.png new file mode 100644 index 0000000..d3bc514 Binary files /dev/null and b/Annotation/resources/icons/previous.png differ diff --git a/Annotation/resources/icons/print.png b/Annotation/resources/icons/print.png new file mode 100644 index 0000000..2f1a0ff Binary files /dev/null and b/Annotation/resources/icons/print.png differ diff --git a/Annotation/resources/icons/redo.png b/Annotation/resources/icons/redo.png new file mode 100644 index 0000000..57de992 Binary files /dev/null and b/Annotation/resources/icons/redo.png differ diff --git a/Annotation/resources/icons/refresh.png b/Annotation/resources/icons/refresh.png new file mode 100644 index 0000000..e46da27 Binary files /dev/null and b/Annotation/resources/icons/refresh.png differ diff --git a/Annotation/resources/icons/reset.png b/Annotation/resources/icons/reset.png new file mode 100644 index 0000000..1556dfe Binary files /dev/null and b/Annotation/resources/icons/reset.png differ diff --git a/Annotation/resources/icons/run.png b/Annotation/resources/icons/run.png new file mode 100644 index 0000000..9010e7a Binary files /dev/null and b/Annotation/resources/icons/run.png differ diff --git a/Annotation/resources/icons/save-as.png b/Annotation/resources/icons/save-as.png new file mode 100644 index 0000000..a838052 Binary files /dev/null and b/Annotation/resources/icons/save-as.png differ diff --git a/Annotation/resources/icons/save.png b/Annotation/resources/icons/save.png new file mode 100644 index 0000000..7da1d7c Binary files /dev/null and b/Annotation/resources/icons/save.png differ diff --git a/Annotation/resources/icons/undo.png b/Annotation/resources/icons/undo.png new file mode 100644 index 0000000..48db6f2 Binary files /dev/null and b/Annotation/resources/icons/undo.png differ diff --git a/Annotation/resources/icons/view.png b/Annotation/resources/icons/view.png new file mode 100644 index 0000000..68da502 Binary files /dev/null and b/Annotation/resources/icons/view.png differ diff --git a/Annotation/resources/icons/zoom-best-fit.png b/Annotation/resources/icons/zoom-best-fit.png new file mode 100644 index 0000000..eb28409 Binary files /dev/null and b/Annotation/resources/icons/zoom-best-fit.png differ diff --git a/Annotation/resources/icons/zoom-in.png b/Annotation/resources/icons/zoom-in.png new file mode 100644 index 0000000..31ac736 Binary files /dev/null and b/Annotation/resources/icons/zoom-in.png differ diff --git a/Annotation/resources/icons/zoom-original.png b/Annotation/resources/icons/zoom-original.png new file mode 100644 index 0000000..8e35414 Binary files /dev/null and b/Annotation/resources/icons/zoom-original.png differ diff --git a/Annotation/resources/icons/zoom-out.png b/Annotation/resources/icons/zoom-out.png new file mode 100644 index 0000000..df5be3c Binary files /dev/null and b/Annotation/resources/icons/zoom-out.png differ diff --git a/Annotation/resources/plaf/debian/changelog b/Annotation/resources/plaf/debian/changelog new file mode 100644 index 0000000..7036b2c --- /dev/null +++ b/Annotation/resources/plaf/debian/changelog @@ -0,0 +1,169 @@ +ist (1.3.4-1) stable; urgency=low + + * Support for Mac OS X leopard (64 bit JVM) + + * Fixed bug in transparent PNG export on Windows platforms + + -- Kevin McGuinness Thur, 27 Mar 2010 19:10:00 +0000 + +ist (1.3.3-1) stable; urgency=low + + * Updated API documentation + + * Larger dialog for segmenter options + + * Linux plugin builds now use GCC-4.1 for better compatibility + + -- Kevin McGuinness Wed, 7 Oct 2009 19:00:00 +0000 + +ist (1.3.2-1) stable; urgency=low + + * Moved more components to the API layer. This includes painters and the image + control. This allows other apps to share core components. + + * Added export transparent PNG option + + -- Kevin McGuinness Wed, 7 Oct 2009 18:00:00 +0000 + +ist (1.3.1-1) stable; urgency=low + + * Updated export HTML feature to export XHTML + + -- Kevin McGuinness Wed, 2 Sep 2009 18:00:00 +0000 + +ist (1.3.0-1) stable; urgency=low + + * Major restructuring of application to ease plugin development + + * New version of SWT + + -- Kevin McGuinness Mon, 24 Aug 2009 18:00:00 +0000 + +ist (1.2.5-1) stable; urgency=low + + * Added code for automated evaluation + + * Update man page and run templates + + -- Kevin McGuinness Mon, 9 Mar 2009 16:21:00 +0000 + +ist (1.2.4-1) stable; urgency=medium + + * Fixed erratic behavior of SIOX segmenter + + * Added a lot of code for automated evaluation + + * Added option to force segmenters to retain all markup pixels in mask. + + -- Kevin McGuinness Fri, 23 Jan 2009 18:00:00 +0000 + +ist (1.2.3-1) stable; urgency=medium + + * Fixed redo bug (redo was calling undo) + + * Segmentation context does not create an Image unless asked to now. This + prevents it initializing the swt Display object unless it needs to, allowing + console applications that use the core segmentation stuff to be created + without initializing the Display. + + -- Kevin McGuinness Thu, 8 Jan 2009 15:00:00 +0000 + +ist (1.2.2-1) stable; urgency=low + + * Fixed application name in menu bar on OS X + + -- Kevin McGuinness Tue, 6 Jan 2009 15:00:00 +0000 + +ist (1.2.1-1) stable; urgency=low + + * Use command key instead of ctrl key for shortcuts on Mac OSX + + * Zip file for app bundle on OS X: it's better supported than tar.gz + + * Modified about box to display SWT version + + * Added standard Command+, binding for preferences on Mac + + * Use small icons in menus on all platforms + + * Removed icons in preference dialog buttons on Mac OS + + * Improved and included several new icons + + * Fixed visual bug on linux: horizontal separators didn't look right in + the export dialog. + + -- Kevin McGuinness Wed, 17 Dec 2008 17:00:00 +0000 + +ist (1.2.0-1) stable; urgency=low + + * New feature: export to HTML image maps integrated. Supports exporting + polygons and rectangles for now. Can export several rollover effects using + the javascript image swapping technique. + + * Fixed bug on Mac OS X: application did not always exit properly + + * Open browser window to show the HTML page when export completes + + * Option to turn on or off the open browser window behavior + + * Best practices: use var for global image preloads. + + -- Kevin McGuinness Tue, 16 Dec 2008 21:37:00 +0000 + +ist (1.1.0-1) stable; urgency=low + + * Several new features are planned for introduction, so the version number + has been incremented to 1.1 + + * Changed context file format. This is now stored as a zip archive including + the image, mask and annotations, so that it is more "self-contained". The + new file format is NOT compatible with the old one. + + -- Kevin McGuinness Tue, 29 Feb 2008 12:25:00 +0000 + +ist (1.0.6-1) stable; urgency=low + + * Added startup check for gdiplus.dll for platforms where it's needed but not + installed by default. Program will now show a useful message and exit gracefully + instead of spewing stack traces on the console and behaving oddly. + + * Fixed bug that caused the auto-apply toggle button to be always disabled + after first image load. + + -- Kevin McGuinness Tue, 28 Feb 2008 10:36:00 +0000 + +ist (1.0.5-1) stable; urgency=medium + + * Fixed bug that caused the brush control (and some other toolbar buttons) to be + disabled after an experiment was cancelled. + + -- Kevin McGuinness Tue, 12 Feb 2008 13:25:00 +0000 + +ist (1.0.4-1) stable; urgency=low + + * Updated the integrated help file (help.html) + + -- Kevin McGuinness Tue, 28 Jan 2008 16:40:00 +0000 + +ist (1.0.3-1) stable; urgency=low + + * MacOSX PowerPC now supported + + * Mostly non-functional changes on Linux, refactoring and the like + + -- Kevin McGuinness Tue, 25 Jan 2008 16:08:00 +0000 + +ist (1.0.2-1) stable; urgency=low + + * Application icon added + + -- Kevin McGuinness Tue, 16 Jan 2008 19:43:00 +0000 + +ist (1.0.1-1) stable; urgency=low + + * Created debian package + + * Support added for 64 bit linux + + -- Kevin McGuinness Tue, 15 Jan 2008 19:43:00 +0000 diff --git a/Annotation/resources/plaf/debian/copyright b/Annotation/resources/plaf/debian/copyright new file mode 100644 index 0000000..32da294 --- /dev/null +++ b/Annotation/resources/plaf/debian/copyright @@ -0,0 +1,10 @@ +ist + +Copyright: Kevin McGuinness + Center for Digital Video Processing + Dublin City University + +2008-01-14 + +The home page of ist is at: +https://www.kspace.cdvp.dcu.ie/public/interactive-segmentation diff --git a/Annotation/resources/plaf/debian/desktop b/Annotation/resources/plaf/debian/desktop new file mode 100644 index 0000000..718ced1 --- /dev/null +++ b/Annotation/resources/plaf/debian/desktop @@ -0,0 +1,10 @@ +# freedesktop.org desktop entry +[Desktop Entry] +Version=1.0 +Type=Application +Name=Interactive Segmentation Tool +Comment=Interactively extract objects from images using various algorithms +Icon=ist +Exec=ist +Terminal=false +Categories=GTK;Graphics diff --git a/Annotation/resources/plaf/debian/ist b/Annotation/resources/plaf/debian/ist new file mode 100644 index 0000000..d1e385d --- /dev/null +++ b/Annotation/resources/plaf/debian/ist @@ -0,0 +1,36 @@ +#!/bin/sh + +# Setup +data=@data@ +main=@main@ +jars=@jars@ + +# Change directory +cd "${data}" + +# This is needed for the browser widget on linux +if [ -z "${MOZILLA_FIVE_HOME}" ]; then + # Check if common locations exist + if [ -d "/usr/lib/firefox" ]; then + export MOZILLA_FIVE_HOME=/usr/lib/firefox + elif [ -d "/usr/lib/mozilla-firefox" ]; then + export MOZILLA_FIVE_HOME=/usr/lib/mozilla-firefox + elif [ -d "/usr/lib/mozilla" ]; then + export MOZILLA_FIVE_HOME=/usr/lib/mozilla + fi +fi + +# Set library path +if [ -n "${MOZILLA_FIVE_HOME}" ]; then + export LD_LIBRARY_PATH=${MOZILLA_FIVE_HOME}:${LD_LIBRARY_PATH} +fi + +# Launch +if [ -n "${JAVA_HOME}" ]; then + ${JAVA_HOME}/bin/java -classpath "${jars}" ${main} $* +else + java -classpath "${jars}" ${main} $* +fi + +cd "$OLDPWD" + diff --git a/Annotation/resources/plaf/debian/ist.1 b/Annotation/resources/plaf/debian/ist.1 new file mode 100644 index 0000000..29faaf6 --- /dev/null +++ b/Annotation/resources/plaf/debian/ist.1 @@ -0,0 +1,29 @@ +.TH "ist" "1" "1.3.3" "Kevin McGuinness" "Graphics" +.SH "NAME" +.LP +ist \- Interactive Segmentation Tool +.SH "SYNTAX" +.LP +ist [options] + +.SH "DESCRIPTION" +.LP +Launches the interactive segmentation tool graphical user interface + +.SH "ENVIRONMENT VARIABLES" +.LP +.TP +\fBMOZILLA_FIVE_HOME\fP +Specifies the location of the mozilla 5 browser +(firefox etc.). This is usually something like +/usr/lib/firefox + +.SH "EXAMPLES" +.LP +To run this program the standard way type: +.LP +$ ist + +.SH "AUTHORS" +.LP +Kevin McGuinness diff --git a/Annotation/resources/plaf/debian/postinst b/Annotation/resources/plaf/debian/postinst new file mode 100644 index 0000000..fb29bea --- /dev/null +++ b/Annotation/resources/plaf/debian/postinst @@ -0,0 +1,4 @@ +#!/bin/sh + +sudo update-desktop-database +sudo gtk-update-icon-cache /usr/share/icons/hicolor diff --git a/Annotation/resources/plaf/debian/postrm b/Annotation/resources/plaf/debian/postrm new file mode 100644 index 0000000..fb29bea --- /dev/null +++ b/Annotation/resources/plaf/debian/postrm @@ -0,0 +1,4 @@ +#!/bin/sh + +sudo update-desktop-database +sudo gtk-update-icon-cache /usr/share/icons/hicolor diff --git a/Annotation/resources/plaf/linux/ist b/Annotation/resources/plaf/linux/ist new file mode 100644 index 0000000..1f45a3a --- /dev/null +++ b/Annotation/resources/plaf/linux/ist @@ -0,0 +1,34 @@ +#!/bin/sh + +jars=istapp.jar:istapi.jar:swt.jar:jface.jar +main=ie.dcu.apps.ist.Main + +# Change directory +cd "`dirname "$0"`" + +# This is needed for the SWT browser widget on linux +if [ -z "${MOZILLA_FIVE_HOME}" ]; then + + # Check if common locations exist + if [ -d "/usr/lib/firefox" ]; then + export MOZILLA_FIVE_HOME=/usr/lib/firefox + elif [ -d "/usr/lib/mozilla-firefox" ]; then + export MOZILLA_FIVE_HOME=/usr/lib/mozilla-firefox + elif [ -d "/usr/lib/mozilla" ]; then + export MOZILLA_FIVE_HOME=/usr/lib/mozilla + fi + +fi + +# Set library path +if [ -n "${MOZILLA_FIVE_HOME}" ]; then + export LD_LIBRARY_PATH=${MOZILLA_FIVE_HOME}:${LD_LIBRARY_PATH} +fi + +if [ -n "${JAVA_HOME}" ]; then + ${JAVA_HOME}/bin/java -classpath "${jars}" ${main} $* +else + java -classpath "${jars}" ${main} $* +fi + +cd "$OLDPWD" diff --git a/Annotation/resources/plaf/mac/Info.plist b/Annotation/resources/plaf/mac/Info.plist new file mode 100644 index 0000000..0fbcac6 --- /dev/null +++ b/Annotation/resources/plaf/mac/Info.plist @@ -0,0 +1,27 @@ + + + + + CFBundleName + @name@ + CFBundleShortVersionString + @version@ + CFBundleGetInfoString + @synopsis@ (v@version@) + CFBundleAllowMixedLocalizations + false + CFBundleInfoDictionaryVersion + 6.0 + CFBundleExecutable + @exename@ + CFBundleDevelopmentRegion + English + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleIconFile + @icons@ + + diff --git a/Annotation/resources/plaf/mac/PkgInfo b/Annotation/resources/plaf/mac/PkgInfo new file mode 100644 index 0000000..6f749b0 --- /dev/null +++ b/Annotation/resources/plaf/mac/PkgInfo @@ -0,0 +1 @@ +APPL???? diff --git a/Annotation/resources/plaf/mac/icon.icns b/Annotation/resources/plaf/mac/icon.icns new file mode 100644 index 0000000..ae867d3 Binary files /dev/null and b/Annotation/resources/plaf/mac/icon.icns differ diff --git a/Annotation/resources/plaf/mac/ist b/Annotation/resources/plaf/mac/ist new file mode 100644 index 0000000..07663d1 --- /dev/null +++ b/Annotation/resources/plaf/mac/ist @@ -0,0 +1,34 @@ +#!/bin/sh + +# What kinda mac are we on +CPU=`uname -p` + +# Absolute path to where the app was launched from +APP_PACKAGE="`dirname "$0"`/../.." +APP_PACKAGE="`cd "${APP_PACKAGE}"; pwd`" + +# Locations of resources, jars, and libs +LIB_DIR="Libraries/${CPU}" + +# Move to the resource directory +cd "${APP_PACKAGE}/Contents/Resources" + +# Establish whether we should use the 32 bit or 64 bit cocoa library +SWT_LIBNAME=swt-cocoa-32.jar +java -version 2>&1 | grep "64-Bit" > /dev/null +if [ "$?" -eq "0" ]; then + SWT_LIBNAME=swt-cocoa-64.jar +fi + +echo "SWT Library: ${SWT_LIBNAME}" + +# Launch app +java \ + -XstartOnFirstThread \ + -classpath "Java/istapp.jar:Java/istapi.jar:Java/jface.jar:Java/${SWT_LIBNAME}" \ + -Dorg.eclipse.swt.internal.carbon.noFocusRing \ + -Dorg.eclipse.swt.internal.carbon.smallFonts \ + @appmain@ $* + +# Go back to the old working directory +cd "${OLDPWD}" diff --git a/Annotation/resources/plaf/windows/application.ico b/Annotation/resources/plaf/windows/application.ico new file mode 100644 index 0000000..ae1ac33 Binary files /dev/null and b/Annotation/resources/plaf/windows/application.ico differ diff --git a/Annotation/resources/plaf/windows/install.xml b/Annotation/resources/plaf/windows/install.xml new file mode 100644 index 0000000..23cb85e --- /dev/null +++ b/Annotation/resources/plaf/windows/install.xml @@ -0,0 +1,56 @@ + + + + + + + + + @name@ + @version@ + + + + @website@ + 1.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Base installation files + + + + + + + diff --git a/Annotation/resources/plaf/windows/installer.ico b/Annotation/resources/plaf/windows/installer.ico new file mode 100644 index 0000000..66d530f Binary files /dev/null and b/Annotation/resources/plaf/windows/installer.ico differ diff --git a/Annotation/resources/plaf/windows/installer.jsmooth b/Annotation/resources/plaf/windows/installer.jsmooth new file mode 100644 index 0000000..823d035 --- /dev/null +++ b/Annotation/resources/plaf/windows/installer.jsmooth @@ -0,0 +1,29 @@ + + + registry + javahome + jrepath + jdkpath + exepath + jview + @input@ + @icon@ + ${EXECUTABLEPATH} + true + @output@ + -1 + com.izforge.izpack.installer.Installer + -1 + + 1.5 + Windowed Wrapper + + Message + Java has not been found on your computer. + Do you want to download it? + + + Debug + 0 + + diff --git a/Annotation/resources/plaf/windows/ist.jsmooth b/Annotation/resources/plaf/windows/ist.jsmooth new file mode 100644 index 0000000..52388f9 --- /dev/null +++ b/Annotation/resources/plaf/windows/ist.jsmooth @@ -0,0 +1,31 @@ + + + registry + javahome + jrepath + jdkpath + exepath + jview + istapp.jar + istapi.jar + swt-win.jar + jface.jar + ${EXECUTABLEPATH} + false + ist.exe + application.ico + -1 + ie.dcu.apps.ist.Main + -1 + 1.5.0 + Windowed Wrapper + + Message + This program needs Java to run. + Please download it at http://www.java.com + + + Debug + 0 + + diff --git a/Annotation/resources/plaf/windows/shortcuts.xml b/Annotation/resources/plaf/windows/shortcuts.xml new file mode 100644 index 0000000..d34c867 --- /dev/null +++ b/Annotation/resources/plaf/windows/shortcuts.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + diff --git a/Annotation/resources/plaf/windows/skeletons/windowed-wrapper/description.skel b/Annotation/resources/plaf/windows/skeletons/windowed-wrapper/description.skel new file mode 100644 index 0000000..52acb08 --- /dev/null +++ b/Annotation/resources/plaf/windows/skeletons/windowed-wrapper/description.skel @@ -0,0 +1,52 @@ + + +false +SKEL_SIMPLEWRAPPER_DESCRIPTION +jwrap.exe +JAVA +102 +103 +Windowed Wrapper + +SKEL_SIMPLEWRAPPER_PROPERTY_MESSAGE_DESCRIPTION +Message + +textarea +Java has not been found on your computer. Do you want to download it? + + +SKEL_SIMPLEWRAPPER_PROPERTY_URL_DESCRIPTION +URL + +string +http://www.java.com + + +SKEL_GENERIC_PROPERTY_SINGLEPROCESS_DESCRIPTION +SingleProcess + +boolean +0 + + +SKEL_GENERIC_SINGLEINSTANCE_DESCRIPTION +SingleInstance + +boolean +0 + + +SKEL_GENERIC_JNISMOOTH_DESCRIPTION +JniSmooth + +boolean +0 + + +SKEL_GENERIC_PROPERTY_DEBUG_DESCRIPTION +Debug + +boolean +0 + + diff --git a/Annotation/resources/plaf/windows/skeletons/windowed-wrapper/jwrap.exe b/Annotation/resources/plaf/windows/skeletons/windowed-wrapper/jwrap.exe new file mode 100755 index 0000000..436402d Binary files /dev/null and b/Annotation/resources/plaf/windows/skeletons/windowed-wrapper/jwrap.exe differ diff --git a/Annotation/src/ie/dcu/apps/ist/AppPrefs.java b/Annotation/src/ie/dcu/apps/ist/AppPrefs.java new file mode 100644 index 0000000..fabc554 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/AppPrefs.java @@ -0,0 +1,259 @@ +package ie.dcu.apps.ist; + +import ie.dcu.swt.SwtUtils; + +import java.util.*; +import java.util.logging.Logger; +import java.util.prefs.*; + +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; + +/** + * Manages application preferences + * + * @author Kevin McGuinness + */ +public class AppPrefs { + + public interface Keys { + public static final String ENABLE_FEEDBACK = "enable-feedback"; + public static final String FOREGROUND_COLOR = "foreground-color"; + public static final String BACKGROUND_COLOR = "background-color"; + public static final String EXPERIMENT_EMBEDDED = "experiment-embedded"; + public static final String CONFIRM_EXIT = "confirm-exit"; + } + + public interface SupportedTypes { + public static final Class INTEGER = Integer.class; + public static final Class DOUBLE = Double.class; + public static final Class FLOAT = Float.class; + public static final Class SHORT = Short.class; + public static final Class BYTE = Byte.class; + public static final Class LONG = Long.class; + public static final Class STRING = String.class; + public static final Class BOOLEAN = Boolean.class; + public static final Class RGB = RGB.class; + } + + + private final Logger log; + private final Preferences prefs; + private final List listeners; + + + public AppPrefs() { + this.log = Logger.getLogger(getClass().getName()); + this.prefs = Preferences.userRoot().node(Application.APP_ID); + this.listeners = new LinkedList(); + + addSwtThreadAdaptionListener(); + } + + + private void addSwtThreadAdaptionListener() { + prefs.addPreferenceChangeListener(new PreferenceChangeListener() { + public void preferenceChange(PreferenceChangeEvent evt) { + firePreferenceChangedSynced(evt); + } + }); + } + + + private void firePreferenceChangedSynced(final PreferenceChangeEvent evt) { + + // Delegate to event SWT event dispatching thread + Display.getDefault().syncExec(new Runnable() { + public void run() { + firePreferenceChanged(evt); + } + }); + + } + + + private void firePreferenceChanged(PreferenceChangeEvent evt) { + for (PreferenceChangeListener listener : listeners) { + listener.preferenceChange(evt); + } + } + + + public void sync() { + try { + prefs.sync(); + } catch (BackingStoreException e) { + log.warning("Error syncing preferences: " + e.getMessage()); + } + } + + + public void flush() { + try { + prefs.flush(); + } catch (BackingStoreException e) { + log.warning("Error writing preferences: " + e.getMessage()); + } + } + + + public void clear() { + try { + prefs.clear(); + } catch (BackingStoreException e) { + log.warning("Error clearing preferences: " + e.getMessage()); + } + } + + + public String[] keys() { + try { + return prefs.keys(); + } catch (BackingStoreException e) { + log.warning("Error retrieving preference keys: " + e.getMessage()); + } + return new String[0]; + } + + + public void remove(String key) { + prefs.remove(key); + } + + + public T get(Class clazz, String key, T def) { + String value = (def != null) ? + get(key, def.toString()) : get(key, null); + + return decode(clazz, value, def); + } + + + public void put(Class clazz, String key, T value) { + prefs.put(key, encode(clazz, value)); + } + + + public void put(String key, String value) { + prefs.put(key, value); + } + + + public String get(String key, String def) { + return prefs.get(key, def); + } + + + public void addPreferenceChangeListener(PreferenceChangeListener pcl) { + listeners.add(pcl); + } + + + public void removePreferenceChangeListener(PreferenceChangeListener pcl) { + listeners.remove(pcl); + } + + + public String encode(Class clazz, T value) { + if (clazz.equals(RGB.class)) { + return encodeRGB((RGB) value); + } else if (value != null) { + return String.valueOf(value); + } else { + return null; + } + } + + + public T decode(Class clazz, String str, T def) { + if (str == null) { + return def; + } else if (isNumeric(clazz)) { + return clazz.cast(decodeNumeric(clazz, str, def)); + } else if (isString(clazz)) { + return clazz.cast(str); + } else if (isBoolean(clazz)) { + return clazz.cast(decodeBoolean(str, (Boolean) def)); + } else if (clazz.equals(RGB.class)) { + return clazz.cast(decodeRGB(str, (RGB) def)); + } else { + log.warning("Unable to decode class: " + clazz.getName()); + } + + return def; + } + + + private boolean isString(Class clazz) { + return clazz.equals(String.class); + } + + + private boolean isBoolean(Class clazz) { + return clazz.equals(Boolean.class); + } + + + + private boolean isNumeric(Class clazz) { + return + clazz.equals(Integer.class) || + clazz.equals(Double.class) || + clazz.equals(Float.class) || + clazz.equals(Short.class) || + clazz.equals(Byte.class) || + clazz.equals(Long.class); + } + + + private RGB decodeRGB(String str, RGB def) { + if (str.startsWith("#")) { + try { + int hex = Integer.parseInt(str.substring(1), 16); + return SwtUtils.int2rgb(hex); + } catch (NumberFormatException e) { + log.warning("Not a valid color: " + str); + } + } + return def; + } + + + private String encodeRGB(RGB rgb) { + return String.format("#%06x", SwtUtils.rgb2int(rgb)); + } + + + private boolean decodeBoolean(String str, boolean def) { + return str.equalsIgnoreCase("true") || + (str.equalsIgnoreCase("false") ? false : def); + } + + + private T decodeNumeric(Class clazz, String s, T def) { + try { + if (clazz.equals(Integer.class)) { + return clazz.cast(Integer.parseInt(s)); + + } else if (clazz.equals(Double.class)) { + return clazz.cast(Double.parseDouble(s)); + + } else if (clazz.equals(Float.class)) { + return clazz.cast(Float.parseFloat(s)); + + } else if (clazz.equals(Short.class)) { + return clazz.cast(Short.parseShort(s)); + + } else if (clazz.equals(Byte.class)) { + return clazz.cast(Byte.parseByte(s)); + + } else if (clazz.equals(Long.class)) { + return clazz.cast(Long.parseLong(s)); + + } + } catch (NumberFormatException ex) { + log.warning("Invalid numeric value in preferences: " + s); + } + return def; + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/AppPrefsManager.java b/Annotation/src/ie/dcu/apps/ist/AppPrefsManager.java new file mode 100644 index 0000000..e41ea3b --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/AppPrefsManager.java @@ -0,0 +1,97 @@ +package ie.dcu.apps.ist; + +import static ie.dcu.segment.annotate.AnnotationType.*; +import static ie.dcu.apps.ist.AppPrefs.Keys.*; +import static ie.dcu.apps.ist.AppPrefs.SupportedTypes.*; +import ie.dcu.segment.annotate.*; +import ie.dcu.apps.ist.AppPrefs.*; + +import java.util.prefs.*; + +import org.eclipse.jface.resource.*; +import org.eclipse.swt.graphics.*; + +/** + * Manages updating various components when preferences change. + * + * @author Kevin McGuinness + */ +class AppPrefsManager implements PreferenceChangeListener { + + private final AppWindow window; + private final ColorRegistry colorRegistry; + private final AppPrefs prefs; + + + public AppPrefsManager(AppWindow window) { + this.window = window; + this.colorRegistry = JFaceResources.getColorRegistry(); + this.prefs = loadPreferences(); + } + + + private AppPrefs loadPreferences() { + AppPrefs prefs = new AppPrefs(); + prefs.addPreferenceChangeListener(this); + return prefs; + } + + + public AppPrefs getPrefs() { + return prefs; + } + + + public void update() { + updateFeedbackEnabled(); + updateBackgroundColor(); + updateForegroundColor(); + updateExperimentEmbedded(); + } + + + public void updateExperimentEmbedded() { + boolean on = prefs.get(BOOLEAN, Keys.EXPERIMENT_EMBEDDED, false); + window.setExperimentModeEmbedded(on); + } + + + public void updateFeedbackEnabled() { + boolean on = prefs.get(BOOLEAN, Keys.ENABLE_FEEDBACK, true); + window.setEnableFeedback(on); + } + + + public void updateForegroundColor() { + RGB color = prefs.get(RGB, Keys.FOREGROUND_COLOR, DEFAULT_FOREGROUND); + colorRegistry.put(AnnotationType.Foreground.key, color); + window.getView().repaint(); + } + + + public void updateBackgroundColor() { + RGB color = prefs.get(RGB, Keys.BACKGROUND_COLOR, DEFAULT_BACKGROUND); + colorRegistry.put(AnnotationType.Background.key, color); + window.getView().repaint(); + } + + + public void preferenceChange(PreferenceChangeEvent evt) { + String pref = evt.getKey(); + + if (pref.equals(ENABLE_FEEDBACK)) { + updateFeedbackEnabled(); + + } else if (pref.equals(FOREGROUND_COLOR)) { + updateForegroundColor(); + + } else if (pref.equals(BACKGROUND_COLOR)) { + updateBackgroundColor(); + + } else if (pref.equals(EXPERIMENT_EMBEDDED)) { + updateExperimentEmbedded(); + } + + } + +} diff --git a/Annotation/src/ie/dcu/apps/ist/AppRecentFiles.java b/Annotation/src/ie/dcu/apps/ist/AppRecentFiles.java new file mode 100644 index 0000000..c2b7b31 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/AppRecentFiles.java @@ -0,0 +1,93 @@ +package ie.dcu.apps.ist; + +import ie.dcu.apps.ist.recent.*; + +import java.io.*; + +/** + * Manages applications recent files list. + * + * @author Kevin McGuinness + */ +public class AppRecentFiles extends RecentFiles { + public static final String APP_SETTINGS_PATH = ".ist"; + public static final String HISTORY_FILE_NAME = ".history"; + + private static AppRecentFiles history; + + + private AppRecentFiles(File store) { + super(store); + } + + + public static AppRecentFiles getInstance() { + if (history == null) { + history = create(); + } + return history; + } + + + private static AppRecentFiles create() { + AppRecentFiles history = null; + try { + history = new AppRecentFiles(getHistoryFile()); + history.load(); + } catch (IOException e) { + getLogger().warning("Unable to create history file: " + e); + } + + return history; + } + + + @Override + public void load() { + try { + super.load(); + } catch (IOException e) { + getLogger().warning("Error loading recent documents list: " + e); + } + } + + @Override + public void store() { + try { + super.store(); + } catch (IOException e) { + getLogger().warning("Error storing recent documents list: " + e); + } + } + + + private static File getHistoryFile() throws IOException { + File file = new File(getSettingsDirectory(), HISTORY_FILE_NAME); + if (file.exists()) { + // Check we can write + if (file.canWrite()) { + return file; + } + } else { + return file; + } + + throw new IOException("History file is unwritable"); + } + + + private static File getSettingsDirectory() throws IOException { + String home = System.getProperty("user.home"); + File settings = new File(home, APP_SETTINGS_PATH); + + if (!settings.exists()) { + if (settings.mkdirs()) { + return settings; + } + } else { + return settings; + } + + throw new IOException("Unable to create application settings directory"); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/AppRecentMenu.java b/Annotation/src/ie/dcu/apps/ist/AppRecentMenu.java new file mode 100644 index 0000000..84fe0cb --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/AppRecentMenu.java @@ -0,0 +1,113 @@ +/** + * + */ +package ie.dcu.apps.ist; + +import ie.dcu.apps.ist.actions.ActionManager; +import ie.dcu.apps.ist.actions.HoverMenuManager; +import ie.dcu.apps.ist.actions.OpenAction; +import ie.dcu.apps.ist.actions.OpenRecentAction; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Properties; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; + +/** + * Recent files menu. + * + * @author Kevin McGuinness + */ +class AppRecentMenu extends HoverMenuManager { + private final AppRecentFiles history; + private final EmptyAction empty; + private final AppWindow window; + private IAction action; + + public AppRecentMenu(AppWindow window, IMenuManager parent) { + super("Open &Recent"); + + this.window = window; + setParent(parent); + history = AppRecentFiles.getInstance(); + add(empty = new EmptyAction()); + addMenuListener(menuListener); + + ActionManager actions = window.getActions(); + if (actions != null) { + OpenAction openAction = actions.get(OpenAction.class); + openAction.addPropertyChangeListener(actionListener); + action = openAction; + } + + try { + Properties props = window.getProperties(); + String icon = props.getProperty("AppRecentMenu.icon", + "file:icons/open-recent.png"); + setImageURL(new URL(icon)); + } catch (MalformedURLException e) { + // Ignore + } + } + + @Override + public void fill(Menu parent, int index) { + super.fill(parent, index); + MenuItem item = getMenuItem(); + if (item != null) { + item.setEnabled(action.isEnabled()); + } + } + + + private void buildMenu() { + removeAll(); + + if (history.empty()) { + add(empty); + } else { + for (File file : history) { + add(new OpenRecentAction(window.getActions(), file)); + } + } + + update(false); + } + + + private final class EmptyAction extends Action { + public EmptyAction() { + setText("No Recent Files"); + setEnabled(false); + } + }; + + + private final IMenuListener menuListener = new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + buildMenu(); + } + }; + + + private final IPropertyChangeListener actionListener + = new IPropertyChangeListener() { + + public void propertyChange(PropertyChangeEvent event) { + MenuItem item = getMenuItem(); + if (item != null) { + item.setEnabled(action.isEnabled()); + } + } + }; + +} diff --git a/Annotation/src/ie/dcu/apps/ist/AppStatus.java b/Annotation/src/ie/dcu/apps/ist/AppStatus.java new file mode 100644 index 0000000..b888e21 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/AppStatus.java @@ -0,0 +1,46 @@ +package ie.dcu.apps.ist; + +import java.net.*; + +import org.eclipse.jface.resource.*; +import org.eclipse.swt.graphics.*; + +/** + * Application status bar message type. + * + * @author Kevin McGuinness + */ +public enum AppStatus { + Information, Warning, Error; + + public Image getIcon() { + String key = key(); + Image image = JFaceResources.getImage(key); + if (image == null) { + ImageRegistry registry = JFaceResources.getImageRegistry(); + ImageDescriptor descriptor = createImageDescriptor(); + registry.put(key, descriptor); + image = registry.get(key); + } + return image; + } + + private ImageDescriptor createImageDescriptor() { + try { + return ImageDescriptor.createFromURL(new URL(key())); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + + private String key() { + switch (this) { + case Information: + return "file:resources/icons/dialog-information.png"; + case Warning: + return "file:resources/icons/dialog-warning.png"; + default: + return "file:resources/icons/dialog-error.png"; + } + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/AppWindow.java b/Annotation/src/ie/dcu/apps/ist/AppWindow.java new file mode 100644 index 0000000..5f32b24 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/AppWindow.java @@ -0,0 +1,725 @@ +package ie.dcu.apps.ist; + +import ie.dcu.apps.ist.actions.*; +import ie.dcu.apps.ist.event.*; +import ie.dcu.apps.ist.exp.Experiment; +import ie.dcu.apps.ist.views.*; +import ie.dcu.segment.*; +import ie.dcu.segment.annotate.*; +import ie.dcu.swt.*; +import ie.dcu.swt.event.*; +import ie.dcu.swt.layout.LayoutFactory; +import ie.dcu.util.*; + +import java.io.*; +import java.net.*; +import java.util.Properties; +import java.util.logging.*; + +import org.eclipse.jface.action.*; +import org.eclipse.jface.resource.*; +import org.eclipse.jface.window.ApplicationWindow; +import org.eclipse.swt.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.*; + +/** + * Main interactive segmentation tool application window. + * + * @author Kevin McGuinness + */ +public class AppWindow extends ApplicationWindow implements FileDropListener { + private static final Logger log = Logger.getLogger("AppWindow"); + + private final Properties props; + + private AppPrefsManager prefsManager; + private ActionManager actions; + private Composite content; + private SegmentationView view; + private Shell shell; + private ImageObserver observer; + private Experiment experiment; + private ExperimentPanel experimentPanel; + private boolean experimentModeEmbedded; + + + public AppWindow() { + super(null); + + props = loadProperties(); + + addMenuBar(); + addStatusLine(); + } + + + @Override + protected boolean canHandleShellCloseEvent() { + if (!ExitAction.confirmExit(this)) { + return false; + } + return super.canHandleShellCloseEvent(); + } + + + private Properties loadProperties() { + try { + return Application.loadProperties(getPropertiesFile()); + } catch (IOException e) { + log.severe("Unable to load properties file " + e.getMessage()); + throw new RuntimeException(e); + } + } + + private String getPropertiesFile() { + return OsUtils.isMacOS() ? "application.mac" : "application"; + } + + + public void updateWindowTitle() { + String title; + if (hasContext()) { + String file = getContext().getFile().getName(); + title = String.format("%s [%s]", Application.APP_NAME, file); + + } else { + title = Application.APP_NAME; + } + + if (isExperimentMode()) { + title += " - Experiment Mode"; + } + + getShell().setText(title); + } + + + private SegmentationView createView(Composite parent) { + + // Load props + Properties props; + try { + props = Application.loadProperties("view"); + } catch (IOException e) { + log.severe("Error loading view properties " + e.getLocalizedMessage()); + throw new RuntimeException(e); + } + + // Create view + SegmentationView view = new SegmentationView(props, parent, 0); + + boolean blocksOnFork = false; + + // Set runnable context + view.setRunnableContext(this, blocksOnFork); + + // Add observer + observer = new ImageObserver(view); + + // Return new view + return view; + } + + + private static ImageDescriptor createImageDescriptor(String url) { + try { + return ImageDescriptor.createFromURL(new URL(url)); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + + + private void updateEnabledActions() { + ActionManager a = getActions(); + boolean ctxAvailable = hasContext(); + boolean experimentMode = isExperimentMode(); + + a.setEnabled(OpenAction.class, !experimentMode); + a.setEnabled(PreferencesAction.class, !experimentMode); + a.setEnabled(SaveAction.class, ctxAvailable && !experimentMode); + a.setEnabled(SaveAsAction.class, ctxAvailable && !experimentMode); + a.setEnabled(ExportViewAction.class, ctxAvailable && !experimentMode); + a.setEnabled(ExportTransparentPNGAction.class, ctxAvailable && !experimentMode); + a.setEnabled(PrintAction.class, ctxAvailable && !experimentMode); + a.setEnabled(CopyAction.class, ctxAvailable && !experimentMode); + a.setEnabled(UndoAction.class, ctxAvailable && view.canUndo()); + a.setEnabled(RedoAction.class, ctxAvailable && view.canRedo()); + a.setEnabled(NextAction.class, ctxAvailable && !experimentMode); + a.setEnabled(PreviousAction.class, ctxAvailable && !experimentMode); + a.setEnabled(OpenExperimentAction.class, !experimentMode); + + updateExportImageMapAction(); + + if (experimentMode) { + + boolean changeSelection = false; + + // Enable experiment segmenters + for (SelectSegmenterAction s : a.getSegmentationActions()) { + Segmenter segmenter = s.getSegmenter(); + boolean enabled = experiment.using(segmenter); + s.setEnabled(enabled); + + if (!s.isEnabled() && s.isChecked()) { + // The selected segmenter has been disabled, + // we need to select a different one + changeSelection = true; + s.setChecked(false); + } + } + + if (changeSelection) { + // Select the first available segmenter + for (SelectSegmenterAction s : a.getSegmentationActions()) { + if (experiment.using(s.getSegmenter())) { + s.setChecked(true); + s.run(); + break; + } + } + } + + } else { + // Enable all select segmenter actions + for (SelectSegmenterAction s : a.getSegmentationActions()) { + s.setEnabled(true); + } + } + } + + private void updateExportImageMapAction() { + ActionManager a = getActions(); + SegmentationContext ctx = getContext(); + + if (ctx != null && !isExperimentMode()) { + AnnotationManager am = ctx.getAnnotations(); + boolean hasObject = am.hasForegroundAnnotation() + && am.hasBackgroundAnnotation(); + a.setEnabled(ExportImageMapAction.class, hasObject); + + } else { + a.setEnabled(ExportImageMapAction.class, false); + } + } + + + private void updateUndoRedoActions() { + ActionManager a = getActions(); + boolean ctxAvailable = hasContext(); + a.setEnabled(UndoAction.class, ctxAvailable && view.canUndo()); + a.setEnabled(RedoAction.class, ctxAvailable && view.canRedo()); + } + + + @Override + protected void configureShell(Shell shell) { + this.shell = shell; + super.configureShell(shell); + updateWindowTitle(); + loadIcons(shell); + shell.setSize(800, 600); + SwtUtils.center(shell); + } + + + private void loadIcons(Shell shell) { + final String[] icons = { + "resources/icons/icon-16.png", + "resources/icons/icon-24.png", + "resources/icons/icon-32.png", + "resources/icons/icon-48.png" + }; + + Image[] images = new Image[icons.length]; + Display display = shell.getDisplay(); + + try { + int i = 0; + for (String file : icons) { + images[i++] = new Image(display, file); + } + + shell.setImages(images); + + } catch (SWTException e) { + log.warning("Error loading application window icons: " + + e.getLocalizedMessage()); + } + } + + + @Override + protected Control createContents(Composite parent) { + content = new Composite(parent, SWT.NONE); + + content.setLayout(LayoutFactory.createGridLayout(0, 0, 2, false)); + + view = createView(content); + view.setLayoutData(LayoutFactory.createGridData()); + view.addContextChangeListener(contextListener); + + SwtUtils.createFileDropTarget(view, this); + + // Done creating contents + getPrefsManager().update(); + updateEnabledActions(); + + return content; + } + + + @Override + protected boolean showTopSeperator() { + return false; + } + + + @Override + protected MenuManager createMenuManager() { + MenuManager bar = new MenuManager(); + + ActionManager actions = getActions(); + + MenuManager file = addMenu(bar, "&File"); + file.add(actions.get(OpenAction.class)); + + file.add(new AppRecentMenu(this, file)); + + file.add(new Separator()); + file.add(actions.get(SaveAction.class)); + file.add(actions.get(SaveAsAction.class)); + file.add(new Separator()); + + // Export menu -> + MenuManager exportMenu = addMenu(file, "&Export", + props.getProperty("ExportMenu.icon")); + + exportMenu.add(actions.get(ExportViewAction.class)); + exportMenu.add(actions.get(ExportImageMapAction.class)); + exportMenu.add(actions.get(ExportTransparentPNGAction.class)); + + file.add(new Separator()); + file.add(actions.get(PrintAction.class)); + file.add(new Separator()); + file.add(actions.get(ExitAction.class)); + + MenuManager edit = addMenu(bar, "&Edit"); + + edit.add(actions.get(UndoAction.class)); + edit.add(actions.get(RedoAction.class)); + edit.add(new Separator()); + edit.add(actions.get(CopyAction.class)); + edit.add(new Separator()); + edit.add(actions.get(PreferencesAction.class)); + + MenuManager tools = addMenu(bar, "&Tools"); + tools.add(actions.get(OpenExperimentAction.class)); + tools.add(new Separator()); + + for (SelectSegmenterAction a : actions.getSegmentationActions()) { + tools.add(a); + } + + tools.add(new Separator()); + tools.add(actions.get(ConfigureSegmenterAction.class)); + + MenuManager go = addMenu(bar, "&Go"); + go.add(actions.get(NextAction.class)); + go.add(actions.get(PreviousAction.class)); + + + MenuManager help = addMenu(bar, "&Help"); + + help.add(actions.get(HelpAction.class)); + help.add(actions.get(AboutAction.class)); + + if (OsUtils.isMacOSX()) { + // Enhance the UI on the Mac + IAction aboutAction = actions.get(AboutAction.class); + IAction prefAction = actions.get(PreferencesAction.class); + Listener quitListener = new Listener() { + public void handleEvent(Event evt) { + getActions().get(ExitAction.class).runWithEvent(evt); + } + }; + CocoaUIEnhancer enhancer = new CocoaUIEnhancer(Application.APP_NAME); + enhancer.hookApplicationMenu(Display.getDefault(), + quitListener, aboutAction, prefAction); + } + + return bar; + } + + + protected static MenuManager addMenu(MenuManager parent, String text) { + MenuManager menu = new HoverMenuManager(text); + parent.add(menu); + return menu; + } + + protected static MenuManager addMenu(MenuManager parent, + String text, String image) { + + MenuManager menu; + try { + menu = new HoverMenuManager(text, image != null ? + new URL(image) : null); + } catch (MalformedURLException e) { + log.log(Level.WARNING, "Malformed URL", e); + menu = new HoverMenuManager(text); + } + + parent.add(menu); + return menu; + } + + + + public void setExperiment(Experiment ex) { + if (experiment != ex) { + experiment = ex; + setContext(null); + + if (ex == null) { + + if (experimentPanel != null) { + experimentPanel.dispose(); + experimentPanel = null; + content.layout(); + } + } else { + + if (experimentModeEmbedded) { + experimentPanel = new ExperimentPanel(this, content, SWT.NONE); + GridData data = new GridData(SWT.FILL, SWT.FILL, false, true); + data.widthHint = 180; + data.verticalIndent = 5; + experimentPanel.setLayoutData(data); + content.layout(); + + } else { + ExperimentPanel.open(this); + } + } + updateEnabledActions(); + updateWindowTitle(); + } + } + + + public Experiment getExperiment() { + return experiment; + } + + + public boolean isExperimentMode() { + return experiment != null; + } + + + public void setExperimentModeEmbedded(boolean on) { + this.experimentModeEmbedded = on; + } + + + public AppPrefs getPrefs() { + return getPrefsManager().getPrefs(); + } + + + AppPrefsManager getPrefsManager() { + if (prefsManager == null) { + prefsManager = new AppPrefsManager(this); + } + return prefsManager; + } + + + public Properties getProperties() { + return props; + } + + + public ActionManager getActions() { + if (actions == null) { + actions = new ActionManager(this); + } + return actions; + } + + + public Shell getShell() { + Shell shell = super.getShell(); + if (shell == null) { + return this.shell; + } + return shell; + } + + + public SegmentationView getView() { + return view; + } + + + public SegmentationContext getContext() { + if (view != null) { + return view.getContext(); + } + return null; + } + + + public File getContextFile() { + if (hasContextFile()) { + return getContext().getFile(); + } + return null; + } + + + public Image getIcon(String url) { + Image image = JFaceResources.getImage(url); + if (image == null) { + ImageRegistry registry = JFaceResources.getImageRegistry(); + ImageDescriptor descriptor = createImageDescriptor(url); + registry.put(url, descriptor); + image = registry.get(url); + } + return image; + } + + + public boolean hasContext() { + if (view != null) { + return view.getContext() != null; + } + return false; + } + + + public boolean hasContextFile() { + return getContext() != null ? getContext().hasContextFile() : false; + } + + + public void setEnableFeedback(boolean on) { + if (observer != null) { + observer.setEnabled(on); + } + } + + + public void setContext(SegmentationContext ctx) { + if (ctx != null) { + // Set a segmenter if one has not been set + if (!view.hasSegmenter()) { + SegmenterRegistry registry = SegmenterRegistry.getInstance(); + view.setSegmenter(registry.getDefault()); + } + } + + // Set context + view.setContext(ctx); + updateWindowTitle(); + } + + + public void status(String message) { + setStatus(message); + } + + + public void status(String format, Object... args) { + setStatus(String.format(format, args)); + } + + + public void status(Image image, String format, Object... args) { + StatusLineManager manager = getStatusLineManager(); + if (manager != null) { + manager.setMessage(image, String.format(format, args)); + } + } + + + public void status(AppStatus s, String format, Object... args) { + if (format == null) { + setStatus(null); + + } else { + StatusLineManager manager = getStatusLineManager(); + if (manager != null) { + if (s == AppStatus.Error) { + manager.setErrorMessage(s.getIcon(), String.format(format, args)); + } else { + manager.setMessage(s.getIcon(), String.format(format, args)); + } + } + } + } + + + public void drop(FileDropEvent evt) { + System.out.println("drop received"); + for (File f : evt.files()) { + if (isAcceptable(f)) { + getActions().get(OpenAction.class).open(f); + break; + } + } + } + + + public boolean isAcceptable(File file) { + String ext = FileUtils.getExtension(file); + return (ext.equals(".ctx") || SwtUtils.getImageFormat(file) != -1); + } + + + private void handleContextChanged(ContextChangedEvent evt) { + + // Remove listener from old context + if (evt.oldContext != null) { + evt.oldContext.removeAnnotationListener(annotationListener); + } + + // Add listener to new context + if (evt.newContext != null) { + evt.newContext.addAnnotationListener(annotationListener); + } + + // Update application state + updateEnabledActions(); + } + + + private void handleAnnotationPerformed(AnnotationEvent e) { + + // Update state of undo and redo menu items + updateUndoRedoActions(); + updateExportImageMapAction(); + } + + + private final ContextChangeListener contextListener = new ContextChangeListener() { + public void contextChanged(ContextChangedEvent evt) { + handleContextChanged(evt); + } + }; + + + private final AnnotationListener annotationListener = new AnnotationAdapter() { + public void annotationsChanged(AnnotationEvent e) { + handleAnnotationPerformed(e); + } + }; + + + private class ImageObserver implements MouseMoveListener, ContextChangeListener { + private static final String MONOSPACE_FONT = "Monospace"; + + private final ImageControl ctrl; + private ImageData image; + private boolean inside; + private boolean enabled; + + + public ImageObserver(SegmentationView view) { + view.addContextChangeListener(this); + view.getCanvas().addMouseMoveListener(this); + ctrl = view.getImageControl(); + contextChanged(view.getContext()); + FontDescriptor fd = FontDescriptor.createFrom(MONOSPACE_FONT, 8, SWT.NORMAL); + JFaceResources.getFontRegistry().put(MONOSPACE_FONT, fd.getFontData()); + } + + + public void setEnabled(boolean enabled) { + if (this.enabled != enabled) { + status(null); + Font font = JFaceResources.getDefaultFont(); + getStatusLineManager().getControl().setFont(font); + this.inside = false; + this.enabled = enabled; + } + } + + + public boolean isEnabled() { + return enabled; + } + + + public void mouseMove(MouseEvent e) { + if (isEnabled()) { + Point pt = getImagePoint(e); + if (pt != null) { + inside(pt, getColor(pt)); + } else { + outside(); + } + } + } + + + private void outside() { + if (inside) { + status(null); + Font font = JFaceResources.getDefaultFont(); + getStatusLineManager().getControl().setFont(font); + inside = false; + } + } + + + private final Point getImagePoint(MouseEvent e) { + if (image != null) { + Point pt = new Point(e.x, e.y); + if (ctrl.imageContains(pt)) { + return ctrl.canvasToImage(pt); + } + } + return null; + } + + + private final RGB getColor(Point pt) { + + int pixel = image.getPixel(pt.x, pt.y); + return image.palette.getRGB(pixel); + } + + + private void inside(Point pt, RGB c) { + if (!inside) { + Font font = JFaceResources.getFont(MONOSPACE_FONT); + getStatusLineManager().getControl().setFont(font); + } + + status(AppStatus.Information, + "Location [%4d,%4d] Color [%3d,%3d,%3d]", + pt.x, pt.y, c.red, c.green, c.blue); + + inside = true; + } + + + public void contextChanged(ContextChangedEvent evt) { + contextChanged(evt.newContext); + } + + + public void contextChanged(SegmentationContext ctx) { + if (ctx != null) { + image = ctx.getImageData(); + } else { + image = null; + } + } + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/Application.java b/Annotation/src/ie/dcu/apps/ist/Application.java new file mode 100644 index 0000000..bbd3b38 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/Application.java @@ -0,0 +1,110 @@ +package ie.dcu.apps.ist; + +import ie.dcu.util.*; + +import java.io.*; +import java.net.*; +import java.security.*; +import java.util.*; + +import static ie.dcu.util.FileUtils.pathJoin; +import static ie.dcu.util.OsUtils.*; + +/** + * Base application. Contains information strings and methods to load + * application wide resources. + * + * @author Kevin McGuinness + */ +public class Application { + public static final String APP_ID = "ist"; + public static final String APP_NAME = "Interactive Segmentation and Annotation Tool"; + public static final String APP_VERSION = "1.3.4"; + public static final String APP_RESOURCE_DIR = "resources"; + + /** + * Default locations to look for plugins + */ + public static final String[] DEFAULT_PLUGIN_SEARCH_PATH + = defaultPluginSearchPath(); + + /** + * Loads a properties file from the application resource area + * (resources/config) + * + * @param name + * The properties file name. ".properties" will be appended if + * necessary. + * @return A Properties object + * @throws IOException + * If there is an error creating the Properties object. + */ + public static Properties loadProperties(String name) throws IOException { + if (!name.endsWith(".properties")) { + name = name + ".properties"; + } + + String path = FileUtils.pathJoin(APP_RESOURCE_DIR, "config", name); + File file = new File(path); + System.out.println("Path:" + file); + return PropsUtils.load(file); + } + + /** + * Returns the users plugins folder + */ + public static String userPluginsFolder() { + return pathJoin(userHome(), ".ist", "plugins"); + } + + /** + * Returns the applications base folder + */ + public static String applicationFolder() { + String apphome = System.getenv("IST_HOME"); + if (apphome != null) { + File file = new File(apphome); + if (file.isDirectory()) { + return file.getAbsolutePath(); + } + } + + ProtectionDomain domain = Application.class.getProtectionDomain(); + CodeSource source = domain.getCodeSource(); + URL location = source.getLocation(); + String path = location.getPath(); + try { + + path = URLDecoder.decode(path, "UTF-8"); + if (isWindows()) { + path = path.substring(1); + } + + path = new File(path).getParent(); + } catch (UnsupportedEncodingException e) { + path = System.getProperty("user.dir"); + } + + return path; + } + + public static String applicationPluginsFolder() { + return pathJoin(applicationFolder(), "plugins"); + } + + public static String osxPluginSearchPath() { + return pathJoin(userHome(), "Library", + "Application Support", APP_NAME, "Plugins"); + } + + private static String[] defaultPluginSearchPath() { + ArrayList paths = new ArrayList(); + paths.add(userPluginsFolder()); + if (isMacOSX()) { + paths.add(osxPluginSearchPath()); + } + paths.add(applicationPluginsFolder()); + return paths.toArray(new String[paths.size()]); + } + +} diff --git a/Annotation/src/ie/dcu/apps/ist/EvaluatorRegistry.java b/Annotation/src/ie/dcu/apps/ist/EvaluatorRegistry.java new file mode 100644 index 0000000..d7bc7b4 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/EvaluatorRegistry.java @@ -0,0 +1,70 @@ +package ie.dcu.apps.ist; + +import ie.dcu.eval.*; + +import java.util.*; + +public class EvaluatorRegistry { + private static EvaluatorRegistry instance; + private final Set evaluators; + + private EvaluatorRegistry() { + evaluators = new LinkedHashSet(); + init(); + } + + + private void init() { + add(new ConfusionMatrixEvaluator()); + add(new BoundaryAccuracyEvaluator()); + } + + + public static EvaluatorRegistry getInstance() { + if (instance == null) { + instance = new EvaluatorRegistry(); + } + return instance; + } + + + public Evaluator find(String name) { + for (Evaluator e : evaluators) { + + // Check name + String ename = e.getName(); + if (ename.equals(name)) { + return e; + } + + // Check class name + String cname = e.getClass().getName(); + if (cname.equals(name)) { + return e; + } + + // Check simple name + String sname = e.getClass().getSimpleName(); + if (sname.equals(name)) { + return e; + } + } + + return null; + } + + + public void add(Evaluator evaluator) { + evaluators.add(evaluator); + } + + + public Set evaluators() { + return Collections.unmodifiableSet(evaluators); + } + + + public Iterator iterator() { + return evaluators.iterator(); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/Main.java b/Annotation/src/ie/dcu/apps/ist/Main.java new file mode 100644 index 0000000..d878efd --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/Main.java @@ -0,0 +1,119 @@ +package ie.dcu.apps.ist; + +import ie.dcu.plugin.*; +import ie.dcu.segment.Segmenter; + +import java.util.logging.Logger; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.*; + +/** + * Application launcher. + * + * @author Kevin McGuinness + */ +public class Main { + public static final Logger log = Logger.getLogger("Main"); + + /** + * Message to show when GDI+ is not installed. + */ + private static final String NO_GDIPLUS = + "Unable to load required library: GDI+ (gdiplus.dll)\n\n" + + "The GDI+ library needs to be installed before this program " + + "can be used on this platform. See the note at the end of " + + "the download page for further details."; + + + public static void main(String[] args) { + System.out.print(Application.DEFAULT_PLUGIN_SEARCH_PATH); + for (String s: Application.DEFAULT_PLUGIN_SEARCH_PATH) { + System.out.println(s); + } + + Display.setAppName(Application.APP_NAME); + check(); + loadPlugins(); + AppWindow window = new AppWindow(); + window.setBlockOnOpen(true); + window.open(); + System.exit(0); + } + + private static void loadPlugins() { + PluginManager manager = new PluginManager(); + for (String path : Application.DEFAULT_PLUGIN_SEARCH_PATH) { + manager.searchPath().add(path); + } + manager.loadPlugins(); + for (Plugin plugin : manager.plugins()) { + String classname = plugin.getMetadata("segmenter"); + if (classname != null) { + loadSegmenterPlugin(plugin, classname); + } + } + } + + private static void loadSegmenterPlugin(Plugin plugin, String classname) { + try { + Segmenter segmenter = (Segmenter) + plugin.loadObject(classname); + + SegmenterRegistry.getInstance().add(segmenter); + + } catch (PluginException e) { + log.severe("Unable to load plugin: " + e); + } + } + + public static boolean contains(String[] args, String argument) { + for (String arg : args) { + while (arg.startsWith("-")) { + arg = arg.substring(1); + } + + if (arg.equals(argument)) { + return true; + } + } + return false; + } + + private static void check() { + // Check for potential missing GDI+ on Win2K, NT, ME 98 + String os = System.getProperty("os.name"); + if (os.equals("Windows 2000") || + os.equals("Windows NT") || + os.equals("Windows ME") || + os.equals("Windows 98")) + { + try { + System.loadLibrary("gdiplus"); + } catch (RuntimeException e) { + exit(NO_GDIPLUS); + } + } + } + + static void exit(String message) { + Display display = Display.getDefault(); + Rectangle rect = display.getBounds(); + + Shell shell = display.getActiveShell(); + if (shell == null) { + shell = new Shell(display, SWT.NO_TRIM); + shell.setBounds(rect.width/2, rect.height/2, 0, 0); + shell.open(); + shell.setText("Error"); + } + + MessageBox box = new MessageBox(shell, SWT.ICON_ERROR); + box.setText("Error"); + box.setMessage(message); + box.open(); + display.dispose(); + System.exit(1); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/PainterRegistry.java b/Annotation/src/ie/dcu/apps/ist/PainterRegistry.java new file mode 100644 index 0000000..b115e2f --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/PainterRegistry.java @@ -0,0 +1,47 @@ +package ie.dcu.apps.ist; + +import ie.dcu.segment.painters.*; + +import java.util.*; + +public class PainterRegistry { + private final LinkedHashMap painters; + + public PainterRegistry() { + painters = new LinkedHashMap(); + init(); + } + + + private void init() { + add(new CombinedPainter()); + add(new OriginalPainter()); + add(new MarkupPainter()); + add(new MaskPainter()); + add(new ForegroundOnlyPainter()); + add(new OutlineOverlayPainter()); + add(new LabelPainter()); + } + + + public void add(SegmentationPainter painter) { + painters.put(painter.getName(), painter); + } + + + public SegmentationPainter get(String painter) { + return painters.get(painter); + } + + + public Collection values() { + return painters.values(); + } + + + public void dispose() { + for (SegmentationPainter p : values()) { + p.dispose(); + } + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/SegmenterRegistry.java b/Annotation/src/ie/dcu/apps/ist/SegmenterRegistry.java new file mode 100644 index 0000000..f3fec09 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/SegmenterRegistry.java @@ -0,0 +1,107 @@ +package ie.dcu.apps.ist; + +import ie.dcu.segment.*; + +import java.util.*; + +/** + * Registry for segmenters. + * + * @author Kevin McGuinness + */ +public class SegmenterRegistry implements Iterable { + private static final String DEFAULT_SEGMENTER_NAME = "IgcSegmenter"; + private static SegmenterRegistry instance; + private final Set segmenters; + + private SegmenterRegistry() { + segmenters = new LinkedHashSet(); + init(); + } + + + private void init() { + // OutlineSegmenter is not very useful + // add(new OutlineSegmenter()); + + // Geodesic Active Contours is too sensitive to parameters + // for general use on natural images. + // add(new SeededGacSegmenter()); + + //add(new SrgSegmenter()); + //add(new IgcSegmenter()); + //add(new BptSegmenter()); + //add(new SioxSegmenter()); + //add(new SpatiogramSegmenter()); + } + + + public static SegmenterRegistry getInstance() { + if (instance == null) { + instance = new SegmenterRegistry(); + } + return instance; + } + + + public Segmenter find(String name) { + for (Segmenter s : segmenters) { + + // Check name + String ename = s.getName(); + if (ename.equals(name)) { + return s; + } + + // Check class name + String cname = s.getClass().getName(); + if (cname.equals(name)) { + return s; + } + + // Check simple name + String sname = s.getClass().getSimpleName(); + if (sname.equals(name)) { + return s; + } + } + + return null; + } + + + public boolean isDefault(Segmenter s) { + if (s != null) { + if (segmenters.size() == 1 && segmenters.contains(s)) { + return true; + } + return s.getClass().getSimpleName().equals(DEFAULT_SEGMENTER_NAME); + } + return false; + } + + + public Segmenter getDefault() { + for (Segmenter s : segmenters) { + if (isDefault(s)) { + return s; + } + } + return null; + } + + + public void add(Segmenter segmenter) { + segmenters.add(segmenter); + } + + + public Set segmenters() { + return Collections.unmodifiableSet(segmenters); + } + + + public Iterator iterator() { + return segmenters.iterator(); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/AboutAction.java b/Annotation/src/ie/dcu/apps/ist/actions/AboutAction.java new file mode 100644 index 0000000..be5d61f --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/AboutAction.java @@ -0,0 +1,109 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.Application; +import ie.dcu.swt.layout.LayoutFactory; + +import org.eclipse.jface.dialogs.*; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.*; + + +/** + * Show an about dialog. + * + * @author Kevin McGuinness + */ +public class AboutAction extends AppAction { + + private AboutBox dialog; + + public AboutAction(ActionManager m) { + super(m); + } + + + @Override + public void run() { + if (dialog == null) { + dialog = new AboutBox(); + } + dialog.open(); + } + + + private class AboutBox extends Dialog { + + private static final String MESSAGE = + " Kevin McGuinness " + + "kevin.mcguinness@eeng.dcu.ie\n" + + " Center for Digital Video Processing\n" + + " Dublin City University.\n" + + " http://www.cdvp.dcu.ie"; + + + private Composite composite; + + + protected AboutBox() { + super(window); + } + + + @Override + protected Control createDialogArea(Composite parent) { + composite = new Composite(parent, SWT.NONE); + composite.setLayout(LayoutFactory.createGridLayout(5, 5)); + + String image = string("aboutImage"); + addImage(image); + addLabel(String.format("Version %s", Application.APP_VERSION), SWT.CENTER); + addLabel(" SWT Version " + swtVersionString(), SWT.CENTER); + addLabel(" Developed By:", SWT.LEFT); + addLink(MESSAGE); + + return composite; + } + + private String swtVersionString() { + return String.format("%d (%s)", SWT.getVersion(), SWT.getPlatform()); + } + + + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, + IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + } + + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("About"); + } + + + private void addLink(String string) { + Link link = new Link(composite, 0); + link.setText(string); + link.setLayoutData(LayoutFactory.createGridData()); + } + + + private void addLabel(String text, int alignment) { + Label label = new Label(composite, 0); + label.setText(text); + label.setAlignment(alignment); + label.setLayoutData(LayoutFactory.createGridData()); + label.setFont(JFaceResources.getBannerFont()); + } + + private void addImage(String url) { + Label label = new Label(composite, 0); + label.setImage(window.getIcon(url)); + label.setLayoutData(LayoutFactory.createGridData()); + } + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/ActionManager.java b/Annotation/src/ie/dcu/apps/ist/actions/ActionManager.java new file mode 100644 index 0000000..b1897f8 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/ActionManager.java @@ -0,0 +1,133 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.*; +import ie.dcu.segment.Segmenter; +import ie.dcu.util.OsUtils; + +import java.io.IOException; +import java.util.*; +import java.util.logging.Logger; + +/** + * Manages application actions. + * + * @author Kevin McGuinness + */ +public class ActionManager { + private static final Logger log = Logger.getLogger("ActionManager"); + + private final AppWindow window; + private final Map actions; + private ArrayList segmenterActions; + private Properties props; + + + public ActionManager(AppWindow window) { + + this.window = window; + this.actions = new HashMap(); + + try { + this.props = Application.loadProperties(getPropertiesFile()); + } catch (IOException e) { + log.severe("Error loading action properties: " + + e.getLocalizedMessage()); + throw new RuntimeException(e); + } + + init(); + } + + + private String getPropertiesFile() { + return OsUtils.isMacOS() ? "actions.mac" : "actions"; + } + + + Properties getProperties() { + return props; + } + + + AppWindow getWindow() { + return window; + } + + + public void init() { + add(new OpenAction(this)); + add(new SaveAction(this)); + add(new SaveAsAction(this)); + add(new AboutAction(this)); + add(new CopyAction(this)); + add(new ExitAction(this)); + add(new ExportViewAction(this)); + add(new ExportImageMapAction(this)); + add(new ExportTransparentPNGAction(this)); + add(new HelpAction(this)); + add(new PreferencesAction(this)); + add(new PrintAction(this)); + add(new RedoAction(this)); + add(new UndoAction(this)); + add(new NextAction(this)); + add(new PreviousAction(this)); + add(new OpenExperimentAction(this)); + add(new ConfigureSegmenterAction(this)); + + // Add select segmenter actions + SegmenterRegistry registry = SegmenterRegistry.getInstance(); + for (Segmenter s : registry) { + add(new SelectSegmenterAction(this, registry, s)); + } + } + + + public void add(AppAction action) { + actions.put(action.id(), action); + } + + + public T get(Class clazz) { + return clazz.cast(actions.get(id(clazz))); + } + + + public T get(Class clazz, String id) { + return clazz.cast(actions.get(id)); + } + + + public void setEnabled(String id, boolean enabled) { + AppAction action = actions.get(id); + if (action != null) { + action.setEnabled(enabled); + } + } + + + public void setEnabled(Class clazz, boolean enabled) { + AppAction action = get(clazz); + if (action != null) { + action.setEnabled(enabled); + } + } + + + public Collection getSegmentationActions() { + if (segmenterActions == null) { + segmenterActions = new ArrayList(); + for (AppAction a : actions.values()) { + if (a instanceof SelectSegmenterAction) { + segmenterActions.add((SelectSegmenterAction) a); + } + } + } + + return Collections.unmodifiableCollection(segmenterActions); + } + + + private String id(Class clazz) { + return clazz.getName(); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/AppAction.java b/Annotation/src/ie/dcu/apps/ist/actions/AppAction.java new file mode 100644 index 0000000..a5a11a8 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/AppAction.java @@ -0,0 +1,122 @@ +package ie.dcu.apps.ist.actions; + +import java.util.logging.*; + +import org.eclipse.jface.dialogs.*; +import org.eclipse.swt.graphics.*; + +import ie.dcu.apps.ist.*; + +/** + * Root class for all application actions. + * + * @author Kevin McGuinness + */ +public class AppAction extends ConfiguredAction { + + // Make easier for subclasses to set status + protected static final AppStatus Information = AppStatus.Information; + protected static final AppStatus Warning = AppStatus.Warning; + protected static final AppStatus Error = AppStatus.Error; + + // Logger + protected final Logger log = Logger.getLogger(getClass().getSimpleName()); + + // Window + protected final AppWindow window; + + // Action manager + protected final ActionManager manager; + + + public AppAction(ActionManager m) { + super(m.getProperties()); + manager = m; + window = m.getWindow(); + } + + + public AppAction(ActionManager m, int style) { + super(m.getProperties(), style); + manager = m; + window = m.getWindow(); + } + + + @Override + public void arm() { + super.arm(); + status(AppStatus.Information, getDescription()); + } + + + @Override + public void disarm() { + super.disarm(); + window.setStatus(null); + } + + + public String id() { + return getClass().getName(); + } + + + protected Image icon(String key) { + String prop = string(key); + if (prop != null) { + return window.getIcon(prop); + } + return null; + } + + + protected void error(String message) { + MessageDialog.openError(window.getShell(), "Error", message); + } + + + protected void error(String format, Object... args) { + error(String.format(format, args)); + } + + + protected void warning(String message) { + MessageDialog.openWarning(window.getShell(), "Warning", message); + } + + + protected void warning(String format, Object... args) { + warning(String.format(format, args)); + } + + + protected void info(String message) { + MessageDialog.openInformation(window.getShell(), "Information", message); + } + + + protected void info(String format, Object... args) { + info(String.format(format, args)); + } + + + protected void log(Level level, String message, Throwable th) { + log.log(level, message, th); + } + + + protected String property(String key) { + return properties.getProperty(key); + } + + + protected void status(AppStatus s, String format, Object... args) { + window.status(s, format, args); + } + + + protected void status(String format, Object... args) { + status(Information, format, args); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/ConfigureSegmenterAction.java b/Annotation/src/ie/dcu/apps/ist/actions/ConfigureSegmenterAction.java new file mode 100644 index 0000000..5221928 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/ConfigureSegmenterAction.java @@ -0,0 +1,24 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.views.SegmentationView; + +/** + * Show the configure segmenter dialog. + * + * @author Kevin McGuinness + */ +public class ConfigureSegmenterAction extends AppAction { + + public ConfigureSegmenterAction(ActionManager m) { + super(m); + } + + + @Override + public void run() { + SegmentationView view = window.getView(); + if (view.canShowOptions()) { + view.showSegmenterOptions(); + } + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/ConfiguredAction.java b/Annotation/src/ie/dcu/apps/ist/actions/ConfiguredAction.java new file mode 100644 index 0000000..24a33f0 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/ConfiguredAction.java @@ -0,0 +1,169 @@ +package ie.dcu.apps.ist.actions; + +import java.net.*; +import java.util.*; +import java.util.logging.*; + +import org.eclipse.jface.action.*; +import org.eclipse.jface.resource.*; + +/** + * Hover Action configured from a properties file. + * + * @author Kevin McGuinness + */ +public class ConfiguredAction extends HoverAction { + private static final Logger log = Logger.getLogger("ConfiguredAction"); + + protected final Properties properties; + private final String id; + + + public ConfiguredAction(Properties properties) { + this(properties, null, AS_PUSH_BUTTON); + } + + + public ConfiguredAction(Properties properties, int style) { + this(properties, null, style); + } + + + public ConfiguredAction(Properties properties, String id, int style) { + super(null, style); + + assert (properties != null); + this.properties = properties; + + if (id != null) { + this.id = id; + } else { + this.id = getClass().getSimpleName(); + } + + configure(); + } + + + private void configure() { + + // Set id + setId(id); + + // Set text + setText(string("text")); + + // Set description + String description; + if ((description = string("description")) != null) { + setDescription(description); + } + + // Set tooltip + String tooltip; + if ((tooltip = string("tooltip")) != null) { + setToolTipText(tooltip); + } + + // Set accelerator + Integer keycode; + if ((keycode = accelerator("accelerator")) != null) { + setAccelerator(keycode); + } + + // Set images + ImageDescriptor im; + + if ((im = image("image")) != null) { + setImageDescriptor(im); + } + + if ((im = image("hoverImage")) != null) { + setHoverImageDescriptor(im); + } + + if ((im = image("disabledImage")) != null) { + setDisabledImageDescriptor(im); + } + + // Set status + Boolean status; + + if ((status = bool("checked") != null)) { + setChecked(status); + } + + if ((status = bool("enabled") != null)) { + setEnabled(status); + } + } + + + protected final Integer accelerator(String key) { + String value = string(key); + + if (value == null) { + return null; + } + + int code = Action.convertAccelerator(value); + + if (code == 0) { + log.warning("No accelerator: " + value); + return null; + } + + if (code == -1) { + log.warning("Not a valid accelerator keycode: " + value); + return null; + } + + return code; + } + + + protected final Boolean bool(String key) { + String value = string(key); + + if (value == null) { + return null; + } + + if (value.trim().equals("true")) { + return true; + } else if (value.trim().equals("false")) { + return false; + } else { + log.warning("Not a boolean value: " + value); + return null; + } + } + + + protected final ImageDescriptor image(String key) { + String url = string(key); + + if (url == null) { + return null; + } + + try { + return ImageDescriptor.createFromURL(new URL(url)); + + } catch (MalformedURLException e) { + log.warning("Invalid URL for image " + url); + return null; + } + } + + + protected final String string(String key) { + return properties.getProperty(key(key)); + } + + + protected final String key(String name) { + return String.format("action.%s.%s", id, name); + } + +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/CopyAction.java b/Annotation/src/ie/dcu/apps/ist/actions/CopyAction.java new file mode 100644 index 0000000..1e7eb65 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/CopyAction.java @@ -0,0 +1,100 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.views.SegmentationView; +import ie.dcu.segment.SegmentationContext; +import ie.dcu.segment.painters.SegmentationPainter; +import ie.dcu.swt.*; + +import java.awt.Toolkit; +import java.awt.datatransfer.*; +import java.awt.image.BufferedImage; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; + +/** + * Copy view to clipboard. + * + * @author Kevin McGuinness + */ +public class CopyAction extends AppAction { + + public CopyAction(ActionManager m) { + super(m); + } + + @Override + public void run() { + + if (window.hasContext()) { + copy(); + } + } + + + private void copy() { + setClipboard(paintContext()); + status("View copied to clipboard as image"); + } + + + private static BufferedImage convert(Image image) { + BufferedImage im = ImageConverter.convert(image.getImageData()); + image.dispose(); + return im; + } + + + public void setClipboard(Image image) { + ImageSelection selection = new ImageSelection(convert(image)); + Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); + clip.setContents(selection, null); + } + + + + private Image paintContext() { + SegmentationView view = window.getView(); + SegmentationContext ctx = window.getContext(); + SegmentationPainter painter = view.getPainter(); + ObservableImage im = createCompatibleImage(ctx); + painter.paint(ctx, im); + return im.getImage(); + } + + + private ObservableImage createCompatibleImage(SegmentationContext ctx) { + Image im = new Image(Display.getCurrent(), ctx.getBounds()); + return new ObservableImage(im); + } + + + private static class ImageSelection implements Transferable { + private BufferedImage image; + + + public ImageSelection(BufferedImage image) { + this.image = image; + } + + + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] { DataFlavor.imageFlavor }; + } + + + public boolean isDataFlavorSupported(DataFlavor flavor) { + return DataFlavor.imageFlavor.equals(flavor); + } + + + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException + { + if (!DataFlavor.imageFlavor.equals(flavor)) { + throw new UnsupportedFlavorException(flavor); + } + return image; + } + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/ExitAction.java b/Annotation/src/ie/dcu/apps/ist/actions/ExitAction.java new file mode 100644 index 0000000..e6ee5c2 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/ExitAction.java @@ -0,0 +1,37 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.*; + +import org.eclipse.jface.dialogs.MessageDialog; + +/** + * Terminate the application. + * + * @author Kevin McGuinness + */ +public class ExitAction extends AppAction { + public ExitAction(ActionManager m) { + super(m); + } + + @Override + public void run() { + if (confirmExit(window)) { + window.close(); + System.exit(0); + } + } + + public static boolean confirmExit(AppWindow window) { + boolean confirm = window.getPrefs().get( + Boolean.class, AppPrefs.Keys.CONFIRM_EXIT, true); + + if (confirm) { + return MessageDialog.openConfirm( + window.getShell(), "Confirm", + "Really exit the application?"); + } + + return true; + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/ExportImageMapAction.java b/Annotation/src/ie/dcu/apps/ist/actions/ExportImageMapAction.java new file mode 100644 index 0000000..3efe020 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/ExportImageMapAction.java @@ -0,0 +1,89 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.dialogs.ExportDialog; +import ie.dcu.apps.ist.export.imagemap.*; +import ie.dcu.apps.ist.views.*; +import ie.dcu.segment.*; +import ie.dcu.swt.ImageConverter; + +import java.awt.image.BufferedImage; +import java.io.*; +import java.util.logging.Level; + +import org.eclipse.swt.program.Program; + +/** + * Export segmentation results as HTML image maps + * + * @author Kevin McGuinness + */ +public class ExportImageMapAction extends AppAction{ + + public ExportImageMapAction(ActionManager m) { + super(m); + } + + @Override + public void run() { + + if (window.hasContext()) { + + // Get options from user + ExportDialog dialog = new ExportDialog(window.getShell()); + ExportDialog.Result result = dialog.open(); + + if (result != null) { + + // Grab image and mask + SegmentationContext ctx = window.getContext(); + SegmentationMask mask = ctx.getMask(); + BufferedImage image = ImageConverter.convert(ctx.getImageData()); + + // Setup exporter + Exporter exporter = new Exporter(image, mask); + exporter.setEffect(result.effect); + exporter.setHtmlFile(result.html); + exporter.setImageFile(result.image); + exporter.setObjectLink(result.link); + exporter.setExportShape(result.shape); + exporter.setObjectDescription(result.description); + String label = SegmentationView.comboLabel.getText(); + if(label.indexOf('{') != -1) + { + label = label.substring(0,label.indexOf('{')-1); + } + exporter.setTitle(label); + + // Export + try { + exporter.export(result.folder); + } catch (IOException e) { + handleError(e); + return; + } catch (ExportException e) { + handleError(e); + return; + } + // for opening the image after saving as ImageMap + if (result.open) { + File file = new File(result.folder, result.html); + Program program = Program.findProgram(".html"); + if (program != null) { + program.execute(file.getAbsolutePath()); + } + } + } + } + } + + private void handleError(Exception e) { + log(Level.WARNING, "Error exporting view as HTML image map", e); + + // Show error dialog + error("Error exporting view as HTML image map: %s", + e.getLocalizedMessage()); + + // Set status message + status(Error, "Error exporting view as HTML image map"); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/ExportTransparentPNGAction.java b/Annotation/src/ie/dcu/apps/ist/actions/ExportTransparentPNGAction.java new file mode 100644 index 0000000..1315e33 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/ExportTransparentPNGAction.java @@ -0,0 +1,148 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.segment.*; +import ie.dcu.swt.SwtUtils; +import ie.dcu.util.FileUtils; + +import java.io.*; +import java.util.logging.Level; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.FileDialog; + +public class ExportTransparentPNGAction extends AppAction { + +private static final String DEFAULT_SUFFIX = ".png"; + + private FileDialog dialog; + private String directory; + + public ExportTransparentPNGAction(ActionManager m) { + super(m); + } + + @Override + public void run() { + if (window.hasContext()) { + File file = getFile(); + if (file != null) { + directory = file.getParent(); + export(file); + } + } + } + + + private void export(File file) { + ImageData im = createSemiTransparentImage(); + try { + SwtUtils.saveImage(im, file); + } catch (IOException e) { + handleError(file, e); + } + } + + + private ImageData createSemiTransparentImage() { + SegmentationContext ctx = window.getContext(); + ImageData image = ctx.getImageData(); + SegmentationMask mask = ctx.getMask(); + ImageData result = new ImageData(image.width, image.height, 32, image.palette); + + int[] pixels = new int[image.width]; + byte[] alphas = new byte[image.width]; + + for (int y = 0; y < image.height; y++) { + image.getPixels(0, y, image.width, pixels, 0); + + int offset = y * mask.cols; + for (int i = 0; i < mask.cols; i++) { + if (mask.values[i+offset] == SegmentationMask.BACKGROUND) { + alphas[i] = (byte) 0x00; + } else { + alphas[i] = (byte) 0xff; + } + } + + result.setPixels(0, y, image.width, pixels, 0); + result.setAlphas(0, y, image.width, alphas, 0); + } + + return result; + } + + + private void handleError(File file, IOException e) { + // Log + log(Level.WARNING, "Error exporting view as image", e); + + // Show error dialog + error("Error exporting view as image %s: %s", + file.getName(), e.getLocalizedMessage() + ); + + // Set status message + status(Error, "Error exporting view as image %s", file.getName()); + } + + + private File getFile() { + createExportDialog(); + + String path = dialog.open(); + if (path != null) { + return checkFile(path); + } + + return null; + } + + + private File checkFile(String path) { + File file = new File(path); + + if (SwtUtils.getImageFormat(file) != -1) { + return file; + } + + // Unknown file extension, so assume jpg + return new File(FileUtils.replaceExtension(path, DEFAULT_SUFFIX)); + } + + + private void createExportDialog() { + if (dialog == null) { + dialog = new FileDialog(window.getShell(), SWT.SAVE | SWT.SHEET); + dialog.setText("Export Transparent PNG"); + dialog.setFilterExtensions(new String[]{"*.png"}); + dialog.setFilterNames(new String[]{"PNG Images"}); + } + + dialog.setFileName(getFileName()); + + String dir = getDirectory(); + if (dir != null) { + // Unfortunately this is buggy on SWT/GTK and + // the filter path isin't always set :'-( + dialog.setFilterPath(dir); + } + } + + private String getFileName() { + File file = window.getContext().getFile(); + return FileUtils.replaceExtension(file.getName(), DEFAULT_SUFFIX); + } + + + private String getDirectory() { + if (directory == null) { + File folder = window.getContext().getFolder(); + directory = (folder != null) ? + directory = folder.getAbsolutePath() : null; + } + + return directory; + } + +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/ExportViewAction.java b/Annotation/src/ie/dcu/apps/ist/actions/ExportViewAction.java new file mode 100644 index 0000000..a6ca7b5 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/ExportViewAction.java @@ -0,0 +1,162 @@ +package ie.dcu.apps.ist.actions; + + +import ie.dcu.apps.ist.views.SegmentationView; +import ie.dcu.segment.SegmentationContext; +import ie.dcu.segment.painters.SegmentationPainter; +import ie.dcu.swt.*; +import ie.dcu.util.FileUtils; + +import java.io.*; +import java.util.logging.Level; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.*; + + +/** + * Export current view as image. + * + * @author Kevin McGuinness + */ +public class ExportViewAction extends AppAction { + + private static final String DEFAULT_SUFFIX = ".png"; + + private FileDialog dialog; + private String directory; + + public ExportViewAction(ActionManager m) { + super(m); + } + + @Override + public void run() { + if (window.hasContext()) { + File file = getFile(); + if (file != null) { + directory = file.getParent(); + export(file); + } + } + } + + + private void export(File file) { + Image im = paintContext(); + + try { + SwtUtils.saveImage(im, file); + status("View successfully exported as %s", file.getName()); + + } catch (IOException e) { + + handleError(file, e); + + } finally { + + im.dispose(); + } + } + + + private void handleError(File file, IOException e) { + // Log + log(Level.WARNING, "Error exporting view as image", e); + + // Show error dialog + error("Error exporting view as image %s: %s", + file.getName(), e.getLocalizedMessage() + ); + + // Set status message + status(Error, "Error exporting view as image %s", file.getName()); + } + + + private File getFile() { + createExportDialog(); + + String path = dialog.open(); + if (path != null) { + return checkFile(path); + } + + return null; + } + + + private File checkFile(String path) { + File file = new File(path); + + if (SwtUtils.getImageFormat(file) != -1) { + return file; + } + + // Unknown file extension, so assume jpg + return new File(FileUtils.replaceExtension(path, DEFAULT_SUFFIX)); + } + + + private void createExportDialog() { + if (dialog == null) { + dialog = new FileDialog(window.getShell(), SWT.SAVE | SWT.SHEET); + dialog.setText(property("ExportViewAction.dialog.text")); + dialog.setFilterExtensions(getFilters()); + dialog.setFilterNames(getFilterNames()); + } + + dialog.setFileName(getFileName()); + + String dir = getDirectory(); + if (dir != null) { + // Unfortunately this is buggy on SWT/GTK and + // the filter path isin't always set :'-( + dialog.setFilterPath(dir); + } + } + + private String getFileName() { + File file = window.getContext().getFile(); + return FileUtils.replaceExtension(file.getName(), DEFAULT_SUFFIX); + } + + + private String getDirectory() { + if (directory == null) { + File folder = window.getContext().getFolder(); + directory = (folder != null) ? + directory = folder.getAbsolutePath() : null; + } + + return directory; + } + + + + private String[] getFilters() { + return new String[] { property("ExportViewAction.dialog.filter.exts") }; + } + + + private String[] getFilterNames() { + return new String[] { property("ExportViewAction.dialog.filter.text") }; + } + + + private Image paintContext() { + SegmentationView view = window.getView(); + SegmentationContext ctx = window.getContext(); + SegmentationPainter painter = view.getPainter(); + ObservableImage im = createCompatibleImage(ctx); + painter.paint(ctx, im); + return im.getImage(); + } + + + private ObservableImage createCompatibleImage(SegmentationContext ctx) { + Image im = new Image(Display.getCurrent(), ctx.getBounds()); + return new ObservableImage(im); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/HelpAction.java b/Annotation/src/ie/dcu/apps/ist/actions/HelpAction.java new file mode 100644 index 0000000..6905dd6 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/HelpAction.java @@ -0,0 +1,126 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.swt.layout.LayoutFactory; + +import org.eclipse.swt.*; +import org.eclipse.swt.browser.Browser; +import org.eclipse.swt.events.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +/** + * Show a help dialog. + * + * @author Kevin McGuinness + */ +public class HelpAction extends AppAction { + + private HelpBox dialog; + + + public HelpAction(ActionManager m) { + super(m); + } + + + @Override + public void run() { + if (dialog == null) { + dialog = new HelpBox(); + } + + if (dialog.available()) { + dialog.open(); + } else { + info("Help browser unavailable on this system"); + } + } + + + /** + * Help dialog box, just wraps a browser. + */ + private class HelpBox { + private Shell shell; + private Composite content; + private Browser browser; + + + public HelpBox() { + createShell(); + createContent(); + } + + + private void createShell() { + shell = new Shell(window.getShell(), SWT.SHELL_TRIM); + + // Prevent the shell from disposing on close + shell.addShellListener(new ShellAdapter() { + public void shellClosed(ShellEvent evt) { + evt.doit = false; + close(); + } + }); + + // Use a fill layout + shell.setLayout(new GridLayout()); + + // Set size and title + shell.setSize(640, 480); + shell.setText("Help"); + } + + + private void createContent() { + // Create content pane + content = new Composite(shell, SWT.BORDER); + content.setLayout(new FillLayout()); + content.setLayoutData(LayoutFactory.createGridData()); + + // Add browser widget + try { + browser = new Browser(content, SWT.NONE); + } catch (SWTError e) { + + // Log warning and return + log.warning("Browser unavailable: " + e.getMessage()); + browser = null; + return; + } + + // Go to help home page + home(); + } + + + public void home() { + String urlString = string("helpURL"); + if (urlString != null) { + go(urlString); + } else { + browser.setText("Help file is unavailable"); + } + } + + + public void go(String url) { + browser.setUrl(url); + } + + + public boolean available() { + return browser != null; + } + + + public void open() { + shell.setVisible(true); + } + + + public void close() { + shell.setVisible(false); + } + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/HoverAction.java b/Annotation/src/ie/dcu/apps/ist/actions/HoverAction.java new file mode 100644 index 0000000..cf933bc --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/HoverAction.java @@ -0,0 +1,88 @@ +package ie.dcu.apps.ist.actions; + +import org.eclipse.jface.action.*; +import org.eclipse.jface.resource.*; + +/** + * Default implementation of {@link IHoverAction}. + * + * @author Kevin McGuinness + */ +public class HoverAction extends Action implements IHoverAction { + private boolean armed = false; + + /** + * Creates a new action with no text and no image. Configure the action later + * using the set methods. + */ + public HoverAction() { + super(); + } + + + /** + * Creates a new action with the given text and no image. + * + * @param text + * the string used as the text for the action, or null + * if there is no text + */ + public HoverAction(String text) { + super(text); + } + + + /** + * Creates a new action with the given text and image. + * + * @param text + * the action's text, or null if there is no text + * @param image + * the action's image, or null if there is no image + */ + public HoverAction(String text, ImageDescriptor image) { + super(text, image); + } + + + /** + * Creates a new action with the given text and style. + * + * @param text + * the action's text, or null if there is no text. + * @param style + * one of + * AS_PUSH_BUTTON, + * AS_CHECK_BOX, + * AS_DROP_DOWN_MENU, + * AS_RADIO_BUTTON, and + * AS_UNSPECIFIED. + */ + public HoverAction(String text, int style) { + super(text, style); + } + + + /** + * Sets the armed property to true. + */ + public void arm() { + armed = true; + } + + + /** + * Sets the armed property to false. + */ + public void disarm() { + armed = false; + } + + + /** + * Returns true if armed. + */ + public boolean isArmed() { + return armed; + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/HoverMenuManager.java b/Annotation/src/ie/dcu/apps/ist/actions/HoverMenuManager.java new file mode 100644 index 0000000..d3b051a --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/HoverMenuManager.java @@ -0,0 +1,149 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.widgets.ImageMenuManager; + +import java.net.URL; +import java.util.*; + +import org.eclipse.jface.action.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.widgets.*; + +/** + * Menu Manager that notifies instances of IHoverAction when they are armed and + * disarmed. + * + * @author Kevin McGuinness + */ +public class HoverMenuManager extends ImageMenuManager { + + /** + * Stores items that have hover listeners added to them. + */ + private final Set hoverItems = new HashSet(); + + + /** + * Create hover menu manager. + */ + public HoverMenuManager() { + init(); + } + + + /** + * Create hover menu manager with id and text. + * + * @param text + * the text for the menu, or null if none. + * @param imageURL + * the menu image url, or null. + */ + public HoverMenuManager(String text, URL imageURL) { + super(text, imageURL); + init(); + } + + + /** + * Create hover menu manager text. + * + * @param text + * the text for the menu, or null if none. + */ + public HoverMenuManager(String text) { + super(text); + init(); + } + + + private void init() { + addMenuListener(menuListener); + } + + + private void addHoverListeners() { + Menu menu = getMenu(); + for (MenuItem item : menu.getItems()) { + addHoverListener(item); + } + } + + + private void addHoverListener(MenuItem item) { + IHoverAction action = getHoverAction(item); + if (action != null) { + addHoverListener(item, action); + } + } + + + private void addHoverListener(MenuItem item, IHoverAction action) { + if (!hoverItems.contains(item)) { + item.addArmListener(new HoverListener(action)); + hoverItems.add(item); + } + } + + + private void disarmAll() { + Menu menu = getMenu(); + for (MenuItem item : menu.getItems()) { + disarm(item); + } + } + + + private void disarm(MenuItem item) { + IHoverAction action = getHoverAction(item); + if (action != null) { + disarm(action); + } + } + + + private void disarm(IHoverAction action) { + if (action.isArmed()) { + action.disarm(); + } + } + + + private IHoverAction getHoverAction(MenuItem item) { + Object data = item.getData(); + if (data instanceof ActionContributionItem) { + IAction action = ((ActionContributionItem) data).getAction(); + + if (action instanceof IHoverAction) { + return (IHoverAction) action; + } + } + return null; + } + + + private IMenuListener menuListener = new IMenuListener2() { + public void menuAboutToShow(IMenuManager manager) { + addHoverListeners(); + } + + public void menuAboutToHide(IMenuManager manager) { + disarmAll(); + } + }; + + + private final class HoverListener implements ArmListener { + private final IHoverAction action; + + public HoverListener(IHoverAction action) { + this.action = action; + } + + + public void widgetArmed(ArmEvent e) { + disarmAll(); + action.arm(); + } + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/IHoverAction.java b/Annotation/src/ie/dcu/apps/ist/actions/IHoverAction.java new file mode 100644 index 0000000..cac72be --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/IHoverAction.java @@ -0,0 +1,34 @@ +package ie.dcu.apps.ist.actions; + +import org.eclipse.jface.action.*; + +/** + * Extension of IAction that supports arming when the mouse hovers over the + * item. This may be useful for displaying descriptions of menu items in the + * status bar, for example. To use hover actions the {@link HoverMenuManager} + * must be used. + * + * @author Kevin McGuinness + */ +public interface IHoverAction extends IAction { + + + /** + * Executed when the action is hovered/armed. + */ + public void arm(); + + + /** + * Executed when the action is de-hovered/disarmed. + */ + public void disarm(); + + + /** + * Query if the action is armed. + * + * @return true if armed. + */ + public boolean isArmed(); +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/NextAction.java b/Annotation/src/ie/dcu/apps/ist/actions/NextAction.java new file mode 100644 index 0000000..900618b --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/NextAction.java @@ -0,0 +1,122 @@ +/** + * + */ +package ie.dcu.apps.ist.actions; + +import java.io.*; +import java.util.*; + +/** + * Jump to the next image in the directory + * + * @author Kevin McGuinness + */ +public class NextAction extends AppAction { + // Supported file extensions + static final String EXTENSIONS = "jpg;jpeg;png;gif;bmp;ctx"; + + private final java.io.FileFilter imageFilter; + + + public NextAction(ActionManager m) { + super(m); + + // Create an image file filter + imageFilter = new SimpleFileFilter(EXTENSIONS); + } + + + @Override + public void run() { + if (window.hasContext()) { + // Get currently opened file + File file = window.getContext().getFile(); + + // Find the one after & open it + File next = findNext(file); + if (next != null) { + manager.get(OpenAction.class).open(next); + } + } + } + + + private File findNext(File file) { + File dir = file.getParentFile(); + + if (dir != null) { + + // List the images + File[] files = dir.listFiles(imageFilter); + + // Need at least one + if (files.length > 1) { + + // Search for ourself... + for (int i = 0; i < files.length; i++) { + + if (files[i].equals(file)) { + + // Use next file (wrap back to first) + return files[(i+1)%files.length]; + } + } + } + } + + return null; + } + +} + +class SimpleFileFilter implements java.io.FileFilter { + + /** + * Holds the list of extensions. It is expected it will be quite + * short, so we use an ArrayList. + */ + private final ArrayList extensions; + + + /** + * Construct a simple file extension filter based on a semicolon separated + * list of file extensions. + * + * @param extensions + * A list of file extensions (ex. jpeg;jpg;png) + */ + public SimpleFileFilter(String extensions) { + String[] exts = extensions.split(";"); + this.extensions = new ArrayList(exts.length); + + for (String s : exts) { + if ((s = s.trim()).length() != 0) { + if (s.startsWith("*")) { + s = s.substring(1); + } + + if (!s.startsWith(".")) { + s = "." + s; + } + + this.extensions.add(s); + } + } + } + + + public boolean accept(File pathname) { + if (pathname.isFile()) { + String name = pathname.getName(); + + // List of extensions should be fairly short.. + for (String ext : extensions) { + if (name.endsWith(ext)) { + return true; + } + } + } + + return false; + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/OpenAction.java b/Annotation/src/ie/dcu/apps/ist/actions/OpenAction.java new file mode 100644 index 0000000..823f176 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/OpenAction.java @@ -0,0 +1,110 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.*; +import ie.dcu.segment.SegmentationContext; + +import java.io.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.widgets.*; + +/** + * Open an image or segmentation context. + * + * @author Kevin McGuinness + */ +public class OpenAction extends AppAction { + + private FileDialog dialog; + + public OpenAction(ActionManager m) { + super(m); + } + + + @Override + public void run() { + File file = getFile(); + if (file != null) { + open(file); + } + } + + + public boolean open(File file) { + String name = file.getName(); + try { + if (SegmentationContext.isContextFile(file)) { + + // Load context + window.setContext(SegmentationContext.load(file)); + status("Opened segmentation context %s successfully", name); + } else { + + // Create context + window.setContext(SegmentationContext.create(file)); + status("Opened image file %s successfully", name); + } + + // Save history + AppRecentFiles.getInstance().add(file); + + // Ok + return true; + + } catch (IOException e) { + + handleError(file, e); + status(Warning, "Proplem opening file %s", name); + + return false; + } + } + + + private void handleError(File file, IOException e) { + + // Get appropriate message + String message = e.getCause() == null ? e.getLocalizedMessage() : + e.getCause().getLocalizedMessage(); + + // Log warning + log.warning(String.format( + "Unable to open %s\n Problem: %s", file, message + )); + + // Show warning dialog + warning("Unable to open %s:\n%s", file.getName(), message); + } + + + private void createOpenDialog() { + // Create dialog if necessary + if (dialog == null) { + dialog = new FileDialog(window.getShell(), SWT.OPEN | SWT.SHEET); + dialog.setText(property("OpenAction.dialog.text")); + dialog.setFilterExtensions(getFilters()); + dialog.setFilterNames(getFilterNames()); + } + } + + private String[] getFilters() { + return new String[] { property("OpenAction.dialog.filter.exts") }; + } + + private String[] getFilterNames() { + return new String[] { property("OpenAction.dialog.filter.text") }; + } + + + private File getFile() { + createOpenDialog(); + + String path = dialog.open(); + if (path != null) { + return new File(path); + } + + return null; + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/OpenExperimentAction.java b/Annotation/src/ie/dcu/apps/ist/actions/OpenExperimentAction.java new file mode 100644 index 0000000..2e27dd4 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/OpenExperimentAction.java @@ -0,0 +1,98 @@ +/** + * + */ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.exp.*; + +import java.io.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.widgets.*; + +/** + * Open an experiment file and switch to experiment mode. + * + * @author Kevin McGuinness + */ +public class OpenExperimentAction extends AppAction { + + private FileDialog dialog; + + + public OpenExperimentAction(ActionManager m) { + super(m); + } + + + @Override + public void run() { + File file = getFile(); + if (file != null) { + open(file); + } + } + + + private void open(File file) { + try { + Experiment ex = ExperimentFactory.getInstance().load(file); + window.setExperiment(ex); + + } catch (IOException ex) { + handleError(file, ex); + } catch (FormatException ex) { + handleError(file, ex); + } + } + + + private void handleError(File file, Exception ex) { + // Get appropriate message + String mesg = ex.getMessage(); + + // Log warning + log.warning(String.format( + "Unable to open experiment file %s\n Problem: %s", file, mesg + )); + + // Show warning dialog + warning("Unable to open experiment file %s:\n%s", file.getName(), mesg); + } + + + private File getFile() { + createOpenDialog(); + + String path = dialog.open(); + if (path != null) { + return new File(path); + } + + return null; + } + + + private void createOpenDialog() { + // Create dialog if necessary + if (dialog == null) { + dialog = new FileDialog(window.getShell(), SWT.OPEN | SWT.SHEET); + dialog.setText(property("OpenExperimentAction.dialog.text")); + dialog.setFilterExtensions(getFilters()); + dialog.setFilterNames(getFilterNames()); + } + } + + private String[] getFilters() { + return new String[] { + property("OpenExperimentAction.dialog.filter.exts") + }; + } + + private String[] getFilterNames() { + return new String[] { + property("OpenExperimentAction.dialog.filter.text") + }; + } + +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/OpenRecentAction.java b/Annotation/src/ie/dcu/apps/ist/actions/OpenRecentAction.java new file mode 100644 index 0000000..299117e --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/OpenRecentAction.java @@ -0,0 +1,25 @@ +package ie.dcu.apps.ist.actions; + +import java.io.*; + +/** + * Action to open a recent file. + * + * @author Kevin McGuinness + */ +public class OpenRecentAction extends AppAction { + private final File file; + + public OpenRecentAction(ActionManager m, File file) { + super(m); + this.file = file; + setText(file.getName()); + String path = file.getAbsolutePath(); + setToolTipText(path); + setDescription(String.format("Open file %s", path)); + } + + public void run() { + manager.get(OpenAction.class).open(file); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/PreferencesAction.java b/Annotation/src/ie/dcu/apps/ist/actions/PreferencesAction.java new file mode 100644 index 0000000..1ccfc38 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/PreferencesAction.java @@ -0,0 +1,24 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.dialogs.*; + +/** + * Show preferences dialog box. + * + * @author Kevin McGuinness + */ +public class PreferencesAction extends AppAction { + private PrefsDialog dialog; + + public PreferencesAction(ActionManager m) { + super(m); + } + + + public void run() { + if (dialog == null) { + dialog = new PrefsDialog(window); + } + dialog.open(); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/PreviousAction.java b/Annotation/src/ie/dcu/apps/ist/actions/PreviousAction.java new file mode 100644 index 0000000..4bfb907 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/PreviousAction.java @@ -0,0 +1,67 @@ +/** + * + */ +package ie.dcu.apps.ist.actions; + +import java.io.*; + +/** + * Jump to previous file in current directory. + * + * @author Kevin McGuinness + */ +public class PreviousAction extends AppAction { + private final java.io.FileFilter imageFilter; + + + public PreviousAction(ActionManager m) { + super(m); + + // Create an image file filter + imageFilter = new SimpleFileFilter(NextAction.EXTENSIONS); + } + + + @Override + public void run() { + if (window.hasContext()) { + // Get currently opened file + File file = window.getContext().getFile(); + + // Find the one before & open it + File next = findPrevious(file); + if (next != null) { + manager.get(OpenAction.class).open(next); + } + } + } + + + + private File findPrevious(File file) { + File dir = file.getParentFile(); + + if (dir != null) { + + // List the images + File[] files = dir.listFiles(imageFilter); + + // Need at least one + if (files.length > 1) { + + // Search for ourself... + for (int i = 0; i < files.length; i++) { + + if (files[i].equals(file)) { + + // Use previous file (wrap back to last) + return files[(i > 0) ? i - 1 : files.length - 1]; + } + } + } + } + + return null; + } + +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/PrintAction.java b/Annotation/src/ie/dcu/apps/ist/actions/PrintAction.java new file mode 100644 index 0000000..3645631 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/PrintAction.java @@ -0,0 +1,107 @@ +package ie.dcu.apps.ist.actions; + + +import ie.dcu.apps.ist.views.SegmentationView; +import ie.dcu.segment.SegmentationContext; +import ie.dcu.segment.painters.SegmentationPainter; +import ie.dcu.swt.ObservableImage; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.printing.*; +import org.eclipse.swt.widgets.Display; + +/** + * Send current view to printer. + * + * @author Kevin McGuinness + */ +public class PrintAction extends AppAction { + + private static final String JOB_NAME = "Interactive Segmentation Tool"; + private PrintDialog dialog; + + public PrintAction(ActionManager m) { + super(m); + } + + @Override + public void run() { + if (window.hasContext()) { + status("Printing..."); + PrinterData data = getPrintData(); + if (data != null) { + print(data); + status("Printing complete"); + } else { + status(null); + } + } + } + + + private PrinterData getPrintData() { + createPrintDialog(); + return dialog.open(); + } + + + private void print(PrinterData data) { + Printer printer = new Printer(data); + try { + print(printer); + + } finally { + printer.dispose(); + } + } + + + private void print(Printer printer) { + if (printer.startJob(JOB_NAME)) { + if (printer.startPage()) { + GC gc = new GC(printer); + try { + paint(gc, printer); + } finally { + gc.dispose(); + } + printer.endPage(); + } + printer.endJob(); + } + } + + + private void paint(GC gc, Printer printer) { + Image im = paintContext(); + try { + gc.drawImage(im, 30, 30); + } finally { + im.dispose(); + } + } + + + private void createPrintDialog() { + if (dialog == null) { + dialog = new PrintDialog(window.getShell(), SWT.SHEET); + } + } + + + private Image paintContext() { + SegmentationView view = window.getView(); + SegmentationContext ctx = window.getContext(); + SegmentationPainter painter = view.getPainter(); + ObservableImage im = createCompatibleImage(ctx); + painter.paint(ctx, im); + return im.getImage(); + } + + + private ObservableImage createCompatibleImage(SegmentationContext ctx) { + Image im = new Image(Display.getCurrent(), ctx.getBounds()); + return new ObservableImage(im); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/RedoAction.java b/Annotation/src/ie/dcu/apps/ist/actions/RedoAction.java new file mode 100644 index 0000000..4e84880 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/RedoAction.java @@ -0,0 +1,23 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.views.SegmentationView; + + +/** + * Redo last annotation action. + * + * @author Kevin McGuinness + */ +public class RedoAction extends AppAction { + public RedoAction(ActionManager m) { + super(m); + } + + @Override + public void run() { + SegmentationView view = window.getView(); + if (view.canRedo()) { + view.redo(); + } + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/SaveAction.java b/Annotation/src/ie/dcu/apps/ist/actions/SaveAction.java new file mode 100644 index 0000000..e652d28 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/SaveAction.java @@ -0,0 +1,120 @@ +package ie.dcu.apps.ist.actions; + +import java.io.*; +import java.util.logging.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.widgets.*; + +/** + * Save segmentation context. + * + * @author Kevin McGuinness + */ +public class SaveAction extends AppAction { + + private FileDialog dialog; + + public SaveAction(ActionManager m) { + super(m); + } + + + @Override + public void run() { + + if (window.hasContext()) { + + File file; + if (window.hasContextFile()) { + file = window.getContextFile(); + } else { + file = getFile(); + } + + if (file != null) { + save(file); + } + } + } + + + private void createSaveDialog() { + if (dialog == null) { + dialog = new FileDialog(window.getShell(), SWT.SAVE | SWT.SHEET); + dialog.setText(property("SaveAction.dialog.text")); + dialog.setFilterExtensions(getFilters()); + dialog.setFilterNames(getFilterNames()); + + String dir = getDirectory(); + if (dir != null) { + dialog.setFilterPath(dir); + } + } + + dialog.setFileName(getFileName()); + } + + + private String getDirectory() { + File folder = window.getContext().getFolder(); + if (folder != null) { + return folder.getAbsolutePath(); + } + + return null; + } + + + private String getFileName() { + return window.getContext().getDefaultFilename(); + } + + + private String[] getFilters() { + return new String[] { property("SaveAction.dialog.filter.exts") }; + } + + + private String[] getFilterNames() { + return new String[] { property("SaveAction.dialog.filter.text") }; + } + + + private File getFile() { + createSaveDialog(); + + String path = dialog.open(); + if (path != null) { + return new File(path); + } + + return null; + } + + + private void save(File file) { + try { + window.getContext().save(file); + window.updateWindowTitle(); + status("Saved context %s successfully", file.getName()); + } catch (IOException e) { + handleError(file, e); + } + } + + + private void handleError(File file, IOException e) { + + // Log + log(Level.SEVERE, "Error saving file", e); + + // Show error dialog + error("Error saving segmentation context %s: %s", + file.getName(), e.getLocalizedMessage() + ); + + // Set status message + status(Error, "Error saving segmentation context %s", file.getName()); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/SaveAsAction.java b/Annotation/src/ie/dcu/apps/ist/actions/SaveAsAction.java new file mode 100644 index 0000000..7db1c26 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/SaveAsAction.java @@ -0,0 +1,112 @@ +package ie.dcu.apps.ist.actions; + +import java.io.*; +import java.util.logging.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.widgets.*; + +/** + * Save segmentation context as. + * + * @author Kevin McGuinness + */ +public class SaveAsAction extends AppAction { + + private FileDialog dialog; + + public SaveAsAction(ActionManager m) { + super(m); + } + + @Override + public void run() { + if (window.hasContext()) { + File file = getFile(); + if (file != null) { + save(file); + } + } + } + + + private void createSaveDialog() { + if (dialog == null) { + dialog = new FileDialog(window.getShell(), SWT.SAVE | SWT.SHEET); + dialog.setText(property("SaveAction.dialog.text")); + dialog.setFilterExtensions(getFilters()); + dialog.setFilterNames(getFilterNames()); + + String dir = getDirectory(); + if (dir != null) { + dialog.setFilterPath(dir); + } + } + + dialog.setFileName(getFileName()); + } + + + private String getDirectory() { + File folder = window.getContext().getFolder(); + if (folder != null) { + return folder.getAbsolutePath(); + } + + return null; + } + + + + private String getFileName() { + return window.getContext().getDefaultFilename(); + } + + + private String[] getFilters() { + return new String[] { property("SaveAction.dialog.filter.exts") }; + } + + + private String[] getFilterNames() { + return new String[] { property("SaveAction.dialog.filter.text") }; + } + + + private File getFile() { + createSaveDialog(); + + String path = dialog.open(); + if (path != null) { + return new File(path); + } + + return null; + } + + + private void save(File file) { + try { + window.getContext().save(file); + window.updateWindowTitle(); + status("Saved context %s successfully", file.getName()); + } catch (IOException e) { + handleError(file, e); + } + } + + + private void handleError(File file, IOException e) { + + // Log + log(Level.SEVERE, "Error saving file", e); + + // Show error dialog + error("Error saving segmentation context %s: %s", + file.getName(), e.getLocalizedMessage() + ); + + // Set status message + status(Error, "Error saving segmentation context %s", file.getName()); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/SelectSegmenterAction.java b/Annotation/src/ie/dcu/apps/ist/actions/SelectSegmenterAction.java new file mode 100644 index 0000000..485ec8a --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/SelectSegmenterAction.java @@ -0,0 +1,60 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.SegmenterRegistry; +import ie.dcu.apps.ist.views.SegmentationView; +import ie.dcu.segment.Segmenter; + +/** + * Segmenter radio buttons. + * + * @author Kevin McGuinness + */ +public class SelectSegmenterAction extends AppAction { + private final Segmenter segmenter; + + public SelectSegmenterAction(ActionManager m, SegmenterRegistry r, Segmenter s) { + super(m, AS_RADIO_BUTTON); + this.segmenter = s; + setText(s.getName()); + setToolTipText(s.getDescription()); + + if (!s.isAvailable()) { + super.setEnabled(false); + setChecked(false); + + String naText = string("NA"); + setToolTipText(naText); + setDescription(naText); + } else { + setChecked(r.isDefault(s)); + } + } + + public void setEnabled(boolean enabled) { + // Disallow enabling unavailable segmentation algorithms + if (!enabled || (segmenter.isAvailable() && enabled)) { + super.setEnabled(enabled); + } + } + + + public Segmenter getSegmenter() { + return segmenter; + } + + + @Override + public String id() { + return segmenter.getClass().getName(); + } + + + @Override + public void run() { + if (isChecked()) { + SegmentationView view = window.getView(); + view.setSegmenter(segmenter); + } + } + +} diff --git a/Annotation/src/ie/dcu/apps/ist/actions/UndoAction.java b/Annotation/src/ie/dcu/apps/ist/actions/UndoAction.java new file mode 100644 index 0000000..d5c67f2 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/actions/UndoAction.java @@ -0,0 +1,22 @@ +package ie.dcu.apps.ist.actions; + +import ie.dcu.apps.ist.views.SegmentationView; + +/** + * Undo last annotation. + * + * @author Kevin McGuinness + */ +public class UndoAction extends AppAction { + public UndoAction(ActionManager m) { + super(m); + } + + @Override + public void run() { + SegmentationView view = window.getView(); + if (view.canUndo()) { + view.undo(); + } + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/controllers/AnnotationTool.java b/Annotation/src/ie/dcu/apps/ist/controllers/AnnotationTool.java new file mode 100644 index 0000000..eb89bb0 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/controllers/AnnotationTool.java @@ -0,0 +1,314 @@ +package ie.dcu.apps.ist.controllers; + + + +import ie.dcu.segment.annotate.*; +import ie.dcu.swt.*; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.Canvas; + +public class AnnotationTool extends MouseMotionAdapter { + private final AnnotationManager manager; + private ImageControl view; + private Canvas canvas; + + private Annotation current; + private AnnotationType type; + private int lineWidth; + private Point last; + private boolean invert; + + + public AnnotationTool(AnnotationManager manager) { + this (manager, null); + } + + /** + * + * @param manager + * @param view + */ + public AnnotationTool(AnnotationManager manager, ImageControl view) { + assert (manager != null); + + this.manager = manager; + this.current = null; + this.lineWidth = 1; + this.type = AnnotationType.Foreground; + + attach(view); + } + + + /** + * + * @param view + */ + public void attach(ImageControl view) { + detach(); + + if (view != null) { + this.view = view; + canvas = view.getCanvas(); + canvas.addMouseListener(this); + canvas.addMouseMoveListener(this); + } + } + + + + public void detach() { + if (view != null) { + canvas.removeMouseListener(this); + canvas.removeMouseMoveListener(this); + view = null; + canvas = null; + current = null; + } + } + + + /** + * Returns the image control associated with the annotation tool. + */ + public ImageControl getView() { + return view; + } + + + /** + * @return the line width + */ + public int getLineWidth() { + return lineWidth; + } + + + /** + * @param width the line width to set + */ + public void setLineWidth(int width) { + assert (width > 0); + this.lineWidth = width; + } + + + /** + * @return the annotation type + */ + public AnnotationType getType() { + return type; + } + + + /** + * @param type the annotation type to set + */ + public void setType(AnnotationType type) { + assert (type != null); + this.type = type; + } + + + + public void begin(Point pt) { + + // Create a new annotation + current = new Annotation(getTypeForUse(), lineWidth, view.canvasToImage(pt)); + + // Give immediate visual feedback + feedback(pt); + + // Set last + last = pt; + } + + + public void append(Point pt) { + + // Update the annotation + current.add(view.canvasToImage(pt)); + + // Give immediate visual feedback + feedback(last, pt); + + // Set last + last = pt; + } + + + public void commit(Point pt) { + // Clip points to image bounds + clip(last, pt); + + // Add point to annotation + current.add(view.canvasToImage(pt)); + + // Add annotation to annotation manager + manager.add(current); + + // Give immediate visual feedback + feedback(last, pt); + + // Mark current annotation as null + current = null; + } + + + public void cancel() { + + // Repaint dirty area + view.repaint(current.getBounds()); + + // Discard annotation + current = null; + } + + + + @Override + public void mouseDown(MouseEvent e) { + if (view == null || !view.isEnabled()) { + current = null; + return; + } + + ObservableImage image = view.getImage(); + if (image != null) { + + if (e.button == 1 || e.button == 3) { + + Point pt = new Point(e.x, e.y); + + if (view.imageContains(pt)) { + + // Check for right mouse button or ctrl modifier + + if (e.button == 3 || (e.stateMask & SWT.CTRL) != 0) { + // Invert type + invert = true; + } else { + invert = false; + } + + if (current != null) { + // Cancel last action + cancel(); + } + + begin(pt); + } + } + } + + return; + } + + + @Override + public void mouseMove(MouseEvent e) { + if (view == null || !view.isEnabled()) { + current = null; + return; + } + + if (current != null) { + Point pt = new Point(e.x, e.y); + + if (view.imageContains(pt)) { + // Normal case: append + append(pt); + + } else { + // Line drawn outside image + + if (view.getImage() != null) { + + commit(pt); + + } else { + // No image: cancel + cancel(); + } + } + } + + } + + + @Override + public void mouseUp(MouseEvent e) { + if (view == null || !view.isEnabled()) { + current = null; + return; + } + + if (current != null) { + Point pt = new Point(e.x, e.y); + + if (view.imageContains(pt)) { + + // Normal case: commit + commit(pt); + } else { + + // Line drawn outside image + if (view.getImage() != null) { + + commit(pt); + } else { + + // No image + cancel(); + } + } + } + } + + + private void clip(Point p, Point q) { + SwtUtils.clip(view.getCanvasImageBounds(), p, q); + } + + + private GC createFeedbackGC() { + GC gc = new GC(canvas); + gc.setAntialias(SWT.ON); + gc.setLineCap(SWT.CAP_ROUND); + gc.setLineJoin(SWT.JOIN_ROUND); + gc.setLineWidth((int) Math.floor(lineWidth * view.getZoom())); + gc.setForeground(getTypeForUse().getColor()); + return gc; + } + + + private void feedback(Point p1) { + feedback(p1, new Point(p1.x+1, p1.y)); + } + + + private void feedback(Point p1, Point p2) { + GC gc = createFeedbackGC(); + gc.setClipping(getClip(p1, p2)); + gc.drawLine(p1.x, p1.y, p2.x, p2.y); + gc.dispose(); + } + + + private Rectangle getClip(Point p1, Point p2) { + int x1 = Math.min(p1.x, p2.x) - lineWidth; + int x2 = Math.max(p1.x, p2.x) + lineWidth; + int y1 = Math.min(p1.y, p2.y) - lineWidth; + int y2 = Math.max(p1.y, p2.y) + lineWidth; + Rectangle r = new Rectangle(x1, y1, x2 - x1, y2 - y1); + return r.intersection(view.getCanvasImageBounds()); + } + + + private AnnotationType getTypeForUse() { + return (invert) ? type.invert() : type; + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/controllers/MouseMotionAdapter.java b/Annotation/src/ie/dcu/apps/ist/controllers/MouseMotionAdapter.java new file mode 100644 index 0000000..70a08e4 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/controllers/MouseMotionAdapter.java @@ -0,0 +1,26 @@ +package ie.dcu.apps.ist.controllers; + +import org.eclipse.swt.events.*; +import org.eclipse.swt.widgets.*; + +public class MouseMotionAdapter extends MouseAdapter implements MouseMoveListener { + + public MouseMotionAdapter() { + } + + + public MouseMotionAdapter(Control control) { + add(control); + } + + + public void add(Control control) { + control.addMouseListener(this); + control.addMouseMoveListener(this); + } + + + public void mouseMove(MouseEvent e) { + } + +} diff --git a/Annotation/src/ie/dcu/apps/ist/dialogs/ExportDialog.java b/Annotation/src/ie/dcu/apps/ist/dialogs/ExportDialog.java new file mode 100644 index 0000000..6807637 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/dialogs/ExportDialog.java @@ -0,0 +1,368 @@ +package ie.dcu.apps.ist.dialogs; + +import ie.dcu.apps.ist.export.imagemap.AreaShape; +import ie.dcu.apps.ist.export.imagemap.RolloverEffect; +import ie.dcu.swt.SwtUtils; +import ie.dcu.swt.layout.LayoutFactory; + +import java.io.File; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Dialog; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +public class ExportDialog extends Dialog { + + public class Result { + public final File folder; + public final String html; + public final String image; + public final String link; + public final String description; + public final AreaShape shape; + public final RolloverEffect effect; + public final boolean open; + + Result() { + folder = new File(folderText.getText().trim()); + html = htmlText.getText().trim(); + image = imageText.getText().trim(); + link = linkText.getText().trim(); + description = descriptionText.getText(); + shape = getShape(); + effect = getEffect(); + open = openButton.getSelection(); + } + }; + + // Result + private Result result; + + // Top level components + private Shell shell; + private Composite content; + private Composite widgets; + private Composite buttons; + + // Widgets + private Text folderText; + private Button browseButton; + private Text htmlText; + private Text imageText; + private Text linkText; + private Button effectCheck; + private Combo effectCombo; + private Button[] shapeRadios; + private Text descriptionText; + private Button openButton; + + // Dialog buttons + private Button cancelButton; + private Button exportButton; + + // Effects + private final String[] ROLLOVER_EFFECTS = { + "Outline Object", "Darken Background", "Highlight Object" + }; + + // Shapes + private final String[] SHAPES = { + "Polygon", "Rectangle", "Circle" + }; + + // Default title + private static final String TITLE = "Export HTML Image Map"; + + public ExportDialog(Shell shell) { + super(shell); + setText(TITLE); + } + + public ExportDialog(Shell shell, int style) { + super(shell, style); + setText(TITLE); + } + + public Result open() { + Shell parent = getParent(); + shell = new Shell(parent, SWT.DIALOG_TRIM | + SWT.APPLICATION_MODAL | SWT.SHEET); + shell.setText(getText()); + shell.setLayout(new FillLayout()); + + createUI(); + + shell.pack(); + + SwtUtils.center(parent, shell); + + shell.open(); + Display display = parent.getDisplay(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) display.sleep(); + } + + return result; + } + + private void createUI() { + // Overall layout + content = new Composite(shell, 0); + content.setLayout(LayoutFactory.createGridLayout(0, 0, 1, false)); + widgets = new Composite(content, 0); + widgets.setLayout(LayoutFactory.createGridLayout(10, 5, 3, false)); + widgets.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + hline(content); + buttons = new Composite(content, 0); + buttons.setLayout(LayoutFactory.createGridLayout(10, 5, 3, false)); + buttons.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + + // Form content + label(widgets, "Export folder:"); + folderText = text(widgets, ""); + browseButton = button(widgets, "Browse..."); + label(widgets, "HTML file name:"); + htmlText = text(widgets, "imagemap.html"); + spacer(widgets); + label(widgets, "Image file name:"); + imageText = text(widgets, "image.png"); + spacer(widgets); + hline(widgets); + label(widgets, "Export shape:"); + shapeRadios = radios(widgets, SHAPES); + // TODO: Enable when available + shapeRadios[2].setEnabled(false); + spacer(widgets); + label(widgets, "Object link:"); + linkText = text(widgets, "http://"); + spacer(widgets); + label(widgets, "Object description:"); + descriptionText = text(widgets, ""); + spacer(widgets); + effectCheck = checkbox(widgets, "Rollover effect:", true, 1); + effectCombo = combo(widgets, ROLLOVER_EFFECTS); + spacer(widgets); + hline(widgets); + openButton = checkbox(widgets, + "Open image map in browser after export completes", true, 3); + + // Button bar + expander(buttons); + cancelButton = new Button(buttons, SWT.PUSH); + cancelButton.setLayoutData(layout4()); + cancelButton.setText("Cancel"); + exportButton = new Button(buttons, SWT.PUSH); + exportButton.setLayoutData(layout4()); + exportButton.setText("Export"); + + // Set the default button + shell.setDefaultButton(exportButton); + + // Add listeners + addListeners(); + } + + private void addListeners() { + + browseButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + String dir = getDirectory(); + if (dir != null) { + folderText.setText(dir); + } + } + }); + + cancelButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + result = null; + shell.dispose(); + } + }); + + exportButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + if (validate()) { + result = new Result(); + shell.dispose(); + } + } + }); + + effectCheck.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event e) { + effectCombo.setEnabled(effectCheck.getSelection()); + } + }); + } + + private boolean validate() { + + File folder = new File(folderText.getText()); + if (!folder.isDirectory()) { + validationError("The export folder must be specified"); + folderText.setFocus(); + return false; + } + + String htmlFile = htmlText.getText().trim(); + if (htmlFile.equals("")) { + validationError("The HTML file name cannot be empty"); + htmlText.setFocus(); + return false; + } + + String imageFile = imageText.getText().trim(); + if (imageFile.equals("")) { + validationError("The image file name cannot be empty"); + imageText.setFocus(); + return false; + } + + return true; + } + + private void validationError(String message) { + MessageBox box = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION); + box.setMessage(message); + box.setText("Invalid Input"); + box.open(); + } + + private AreaShape getShape() { + for (Button bt : shapeRadios) { + if (bt.getSelection()) { + return AreaShape.valueOf(bt.getText()); + } + } + return null; + } + + private RolloverEffect getEffect() { + RolloverEffect effect = null; + if (effectCheck.getSelection()) { + String text = effectCombo.getText(); + if (text.equals("Outline Object")) { + effect = RolloverEffect.outlineObject(); + } else if (text.equals("Darken Background")) { + effect = RolloverEffect.darkenBackground(); + } else if (text.equals("Highlight Object")) { + effect = RolloverEffect.brightenForeground(); + } + } + return effect; + } + + private String getDirectory() { + DirectoryDialog dialog = new DirectoryDialog(shell); + return dialog.open(); + } + + private Button[] radios(Composite parent, String ... items) { + Composite c = new Composite(parent, SWT.NONE); + c.setLayout(LayoutFactory.createGridLayout(5, 10, items.length, false)); + c.setLayoutData(layout2()); + + Button[] bts = new Button[items.length]; + for (int i = 0; i < bts.length; i++) { + bts[i] = new Button(c, SWT.RADIO); + bts[i].setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); + bts[i].setText(items[i]); + bts[i].setSelection(i == 0); + } + + return bts; + } + + private Label hline(Composite parent) { + Label label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); + GridData data = new GridData(SWT.FILL, SWT.CENTER, false, false); + data.horizontalSpan = 3; + data.heightHint = 10; + label.setLayoutData(data); + return label; + } + + private Label spacer(Composite parent) { + Label label = new Label(parent, SWT.NONE); + label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); + return label; + } + + private Label expander(Composite parent) { + Label label = new Label(parent, SWT.NONE); + label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + return label; + } + + private Combo combo(Composite parent, String ... items) { + Combo combo = new Combo(parent, SWT.READ_ONLY); + combo.setItems(items); + combo.setLayoutData(layout2()); + if (items.length > 0) { + combo.select(0); + } + return combo; + } + + private Button checkbox(Composite parent, String text, + boolean checked, int span) { + + Button bt = new Button(parent, SWT.CHECK); + bt.setText(text); + bt.setSelection(checked); + GridData data = layout1(); + data.horizontalSpan = span; + bt.setLayoutData(data); + return bt; + } + + private Label label(Composite parent, String text) { + Label label = new Label(parent, SWT.NONE); + label.setText(text); + label.setLayoutData(layout1()); + return label; + } + + private Text text(Composite parent, String value) { + Text text = new Text(parent, SWT.BORDER | SWT.SINGLE); + text.setText(value); + text.setLayoutData(layout2()); + return text; + } + + private Button button(Composite parent, String text) { + Button bt = new Button(parent, SWT.PUSH); + bt.setText(text); + bt.setLayoutData(layout3()); + return bt; + } + + private GridData layout1() { + return new GridData(SWT.LEFT, SWT.CENTER, false, false); + } + + private GridData layout2() { + return new GridData(SWT.FILL, SWT.CENTER, true, false); + } + + private GridData layout3() { + return new GridData(SWT.RIGHT, SWT.CENTER, false, false); + } + + private GridData layout4() { + return new GridData(SWT.RIGHT, SWT.BOTTOM, false, false); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/dialogs/PrefsDialog.java b/Annotation/src/ie/dcu/apps/ist/dialogs/PrefsDialog.java new file mode 100644 index 0000000..9ea4eeb --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/dialogs/PrefsDialog.java @@ -0,0 +1,435 @@ +package ie.dcu.apps.ist.dialogs; + +import static ie.dcu.segment.annotate.AnnotationType.*; +import ie.dcu.apps.ist.*; +import ie.dcu.apps.ist.AppPrefs.Keys; +import ie.dcu.apps.ist.widgets.ColorSelector; +import ie.dcu.swt.SwtUtils; +import ie.dcu.swt.layout.LayoutFactory; + +import java.util.*; + +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +public class PrefsDialog { + private static final String APPLICATION = "application"; + private static final String STATUS = "status"; + private static final String VIEW = "view"; + private static final String TITLE = "title"; + private static final String GENERAL = "general"; + private static final String CLOSE = "close"; + private static final String RESET = "reset"; + private static final String TEXT = "text"; + private static final String ICON = "icon"; + private static final String TTIP = "ttip"; + private static final String EXPERIMENT = "experiment"; + + private final AppWindow window; + private final AppPrefs prefs; + private final Shell shell; + private final Composite content; + private final TabFolder folder; + private final Composite buttonBar; + private final Composite generalTab; + private final Button resetButton; + private final Button closeButton; + private final HashMap controls; + + private transient GridData gd; + + + public PrefsDialog(AppWindow window) { + this.window = window; + this.prefs = window.getPrefs(); + this.shell = createShell(); + this.content = createContent(); + this.folder = createTabFolder(); + this.buttonBar = createButtonBar(); + this.generalTab = createTab(GENERAL); + this.resetButton = createResetButton(); + this.closeButton = createCloseButton(); + this.controls = new HashMap(); + + createControls(); + loadPreferences(); + + SwtUtils.center(window.getShell(), shell); + } + + + private void createControls() { + // Initialize general tab + createBanner(generalTab, APPLICATION); + + createLabel(generalTab, Keys.CONFIRM_EXIT); + createCheckBox(generalTab, Keys.CONFIRM_EXIT); + + createBanner(generalTab, STATUS); + + createLabel(generalTab, Keys.ENABLE_FEEDBACK); + createCheckBox(generalTab, Keys.ENABLE_FEEDBACK); + + createBanner(generalTab, VIEW); + + createLabel(generalTab, Keys.FOREGROUND_COLOR); + createColorSelector(generalTab, Keys.FOREGROUND_COLOR); + + createLabel(generalTab, Keys.BACKGROUND_COLOR); + createColorSelector(generalTab, Keys.BACKGROUND_COLOR); + + createBanner(generalTab, EXPERIMENT); + + createLabel(generalTab, Keys.EXPERIMENT_EMBEDDED); + createCheckBox(generalTab, Keys.EXPERIMENT_EMBEDDED); + } + + + private void loadPreferences() { + + // Load confirm exit + loadBool(Keys.CONFIRM_EXIT, true); + + // Load enable feedback + loadBool(Keys.ENABLE_FEEDBACK, true); + + // Load foreground color + loadColor(Keys.FOREGROUND_COLOR, DEFAULT_FOREGROUND); + + // Load background color + loadColor(Keys.BACKGROUND_COLOR, DEFAULT_BACKGROUND); + + // Load experiment embedded + loadBool(Keys.EXPERIMENT_EMBEDDED, false); + } + + + private Shell createShell() { + Shell s = new Shell(window.getShell(), SWT.SHELL_TRIM | SWT.SHEET); + + // Add listener + s.addListener(SWT.Close, adapter); + + // Use a fill layout + s.setLayout(new FillLayout()); + + // Set size and title + s.setSize(420, 450); + s.setText(property(TITLE, "Preferences")); + + return s; + } + + + private Composite createContent() { + + // Create content pane with grid layout + Composite c = new Composite(shell, 0); + c.setLayout(new GridLayout()); + return c; + } + + + private TabFolder createTabFolder() { + // Create folder + TabFolder f = new TabFolder(content, SWT.TOP); + + // Layout folder + f.setLayoutData(LayoutFactory.createGridData()); + + return f; + } + + + private Composite createButtonBar() { + // Create bar + Composite bar = new Composite(content, SWT.NONE); + + // Layout bar + bar.setLayout(LayoutFactory.createGridLayout(0, 0, 2, true)); + bar.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false)); + + return bar; + } + + + private Composite createTab(String name) { + // Create item + TabItem item = new TabItem(folder, SWT.NONE); + item.setText(property(name, "tab", name)); + + // Create control + Composite control = new Composite(folder, SWT.NONE); + control.setLayout(LayoutFactory.createGridLayout(10, 5, 2, false)); + + // Set control + item.setControl(control); + + // Return control (item can be ignored) + return control; + } + + + private Button createResetButton() { + // Create button + Button bt = createButton(buttonBar, RESET, SWT.PUSH); + + // Layout button + gd = new GridData(SWT.LEFT, SWT.BOTTOM, true, false); + gd.minimumWidth = 85; + bt.setLayoutData(gd); + + // Done + return bt; + } + + + private Button createCloseButton() { + // Create button + Button bt = createButton(buttonBar, CLOSE, SWT.PUSH); + + // Layout button + gd = new GridData(SWT.RIGHT, SWT.BOTTOM, true, false); + gd.minimumWidth = 85; + bt.setLayoutData(gd); + + // Done + return bt; + } + + + private Button createCheckBox(Composite tab, String key) { + Button bt = new Button(tab, SWT.CHECK); + + // Layout button + gd = new GridData(SWT.RIGHT, SWT.CENTER, false, false); + gd.horizontalIndent = 5; + bt.setLayoutData(gd); + + // Add listener + bt.addListener(SWT.Selection, adapter); + bt.setData(key); + + // Put into controls + controls.put(key, bt); + + // Done + return bt; + } + + + private ColorSelector createColorSelector(Composite tab, String key) { + ColorSelector cs = new ColorSelector(tab); + + // Layout button + gd = new GridData(SWT.RIGHT, SWT.CENTER, false, false); + gd.horizontalIndent = 10; + gd.minimumWidth = 80; + cs.setLayoutData(gd); + + // Add listener + cs.addListener(SWT.Selection, adapter); + cs.setData(key); + + // Put into controls + controls.put(key, cs); + + // Done + return cs; + } + + + private Label createBanner(Composite tab, String key) { + // Create label + Label lb = new Label(tab, SWT.NONE); + lb.setText(property(key, key)); + lb.setFont(JFaceResources.getBannerFont()); + + // Layout label + gd = new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1); + gd.verticalIndent = 5; + lb.setLayoutData(gd); + + return lb; + } + + + private Label createLabel(Composite tab, String key) { + // Create label + Label lb = new Label(tab, SWT.NONE); + lb.setText(property(key, TEXT, key)); + + // Layout label + gd = new GridData(SWT.LEFT, SWT.CENTER, true, false); + gd.horizontalIndent = 5; + lb.setLayoutData(gd); + + return lb; + } + + + private Button createButton(Composite parent, String key, int style) { + Button bt = new Button(parent, style); + + // Configure button + configure(bt, key); + + // Add listener + bt.addListener(SWT.Selection, adapter); + + // Done + return bt; + } + + + protected void handleEvent(Event event) { + switch (event.type) { + case SWT.Close: + handleClose(event); + break; + case SWT.Selection: + handleSelection(event); + break; + } + + } + + + private void handleClose(Event event) { + // Prevent the shell from disposing on close + event.doit = false; + close(); + } + + + private void handleSelection(Event event) { + if (event.widget == closeButton) { + close(); + } else if (event.widget == resetButton) { + reset(); + } else { + Object data = event.widget.getData(); + if (data instanceof String) { + handleSelection(event, (String) data); + } + } + + } + + + private void handleSelection(Event event, String key) { + + if (key.equals(Keys.ENABLE_FEEDBACK)) { + storeBool(key); + + } else if (key.equals(Keys.FOREGROUND_COLOR)) { + + storeColor(key); + + } else if (key.equals(Keys.BACKGROUND_COLOR)) { + + storeColor(key); + + } else if (key.equals(Keys.EXPERIMENT_EMBEDDED)) { + + storeBool(key); + + } else if (key.equals(Keys.CONFIRM_EXIT)) { + + storeBool(key); + } + + } + + + private void storeBool(String key) { + Boolean bool = control(Button.class, key).getSelection(); + prefs.put(Boolean.class, key, bool); + } + + + private void storeColor(String key) { + RGB color = control(ColorSelector.class, key).getColor(); + if (color != null) { + prefs.put(RGB.class, key, color); + } + } + + + private void loadBool(String key, boolean def) { + Boolean bool = prefs.get(Boolean.class, key, def); + control(Button.class, key).setSelection(bool); + } + + + private void loadColor(String key, RGB def) { + RGB color = prefs.get(RGB.class, key, def); + control(ColorSelector.class, key).setColor(color); + } + + + public void reset() { + // Set defaults + prefs.clear(); + + // Reload + loadPreferences(); + } + + + public void close() { + shell.setVisible(false); + } + + + public void open() { + shell.setVisible(true); + } + + + private void configure(Button bt, String key) { + // Read properties + String text = property(key, TEXT, ""); + String icon = property(key, ICON, null); + String ttip = property(key, TTIP, null); + + // Set values + bt.setText(text); + bt.setImage(image(icon)); + bt.setToolTipText(ttip); + bt.setData(key); + } + + + private T control(Class clazz, String key) { + return clazz.cast(controls.get(key)); + } + + + private String property(String key, String def) { + Properties p = window.getProperties(); + return p.getProperty(String.format("PrefsDialog.%s", key), def); + } + + + private String property(String key, String type, String def) { + Properties p = window.getProperties(); + String prop = String.format("PrefsDialog.%s.%s", key, type); + return p.getProperty(prop, def); + } + + + private Image image(String url) { + return (url != null) ? window.getIcon(url) : null; + } + + + private final Listener adapter = new Listener() { + public void handleEvent(Event event) { + PrefsDialog.this.handleEvent(event); + } + }; +} diff --git a/Annotation/src/ie/dcu/apps/ist/event/ContextChangeListener.java b/Annotation/src/ie/dcu/apps/ist/event/ContextChangeListener.java new file mode 100644 index 0000000..8c617a0 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/event/ContextChangeListener.java @@ -0,0 +1,7 @@ +package ie.dcu.apps.ist.event; + +import java.util.*; + +public interface ContextChangeListener extends EventListener { + public void contextChanged(ContextChangedEvent evt); +} diff --git a/Annotation/src/ie/dcu/apps/ist/event/ContextChangedEvent.java b/Annotation/src/ie/dcu/apps/ist/event/ContextChangedEvent.java new file mode 100644 index 0000000..638dad9 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/event/ContextChangedEvent.java @@ -0,0 +1,24 @@ +package ie.dcu.apps.ist.event; + + +import ie.dcu.segment.SegmentationContext; + +import java.util.*; + + +public class ContextChangedEvent extends EventObject { + private static final long serialVersionUID = 1L; + + public final SegmentationContext oldContext; + public final SegmentationContext newContext; + + public ContextChangedEvent( + Object source, + SegmentationContext oldContext, + SegmentationContext newContext + ) { + super(source); + this.oldContext = oldContext; + this.newContext = newContext; + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/event/StateEvent.java b/Annotation/src/ie/dcu/apps/ist/event/StateEvent.java new file mode 100644 index 0000000..38c5bbc --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/event/StateEvent.java @@ -0,0 +1,11 @@ +package ie.dcu.apps.ist.event; + +import java.util.*; + +public class StateEvent extends EventObject { + private static final long serialVersionUID = 1L; + + public StateEvent(Object source) { + super(source); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/event/StateListener.java b/Annotation/src/ie/dcu/apps/ist/event/StateListener.java new file mode 100644 index 0000000..525f253 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/event/StateListener.java @@ -0,0 +1,13 @@ +/** + * + */ +package ie.dcu.apps.ist.event; + +import java.util.*; + +/** + * @author Kevin McGuinness + */ +public interface StateListener extends EventListener { + public void stateChanged(StateEvent evt); +} diff --git a/Annotation/src/ie/dcu/apps/ist/event/TickerEvent.java b/Annotation/src/ie/dcu/apps/ist/event/TickerEvent.java new file mode 100644 index 0000000..ae6124f --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/event/TickerEvent.java @@ -0,0 +1,25 @@ +package ie.dcu.apps.ist.event; + + +import ie.dcu.apps.ist.widgets.Ticker; + +import java.util.EventObject; + +public class TickerEvent extends EventObject { + private static final long serialVersionUID = 755693053854019177L; + + private final long elapsed; + + public TickerEvent(Ticker t, long elapsed) { + super(t); + this.elapsed = elapsed; + } + + public Ticker getTicker() { + return (Ticker) getSource(); + } + + public long getElapsed() { + return elapsed; + } +}; diff --git a/Annotation/src/ie/dcu/apps/ist/event/TickerListener.java b/Annotation/src/ie/dcu/apps/ist/event/TickerListener.java new file mode 100644 index 0000000..26b6269 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/event/TickerListener.java @@ -0,0 +1,7 @@ +package ie.dcu.apps.ist.event; + +import java.util.*; + +public interface TickerListener extends EventListener { + public void tick(TickerEvent evt); +} diff --git a/Annotation/src/ie/dcu/apps/ist/event/TimeoutEvent.java b/Annotation/src/ie/dcu/apps/ist/event/TimeoutEvent.java new file mode 100644 index 0000000..70659c3 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/event/TimeoutEvent.java @@ -0,0 +1,24 @@ +/** + * + */ +package ie.dcu.apps.ist.event; + + +import ie.dcu.apps.ist.widgets.SwtTimer; + +import java.util.EventObject; + +/** + * @author Kevin McGuinness + */ +public class TimeoutEvent extends EventObject { + private static final long serialVersionUID = 1L; + + public TimeoutEvent(SwtTimer source) { + super(source); + } + + public SwtTimer getTimer() { + return (SwtTimer) getSource(); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/event/TimeoutListener.java b/Annotation/src/ie/dcu/apps/ist/event/TimeoutListener.java new file mode 100644 index 0000000..c682041 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/event/TimeoutListener.java @@ -0,0 +1,13 @@ +/** + * + */ +package ie.dcu.apps.ist.event; + +import java.util.*; + +/** + * @author Kevin McGuinness + */ +public interface TimeoutListener extends EventListener { + public void timeoutOccured(TimeoutEvent evt); +} diff --git a/Annotation/src/ie/dcu/apps/ist/exp/Experiment.java b/Annotation/src/ie/dcu/apps/ist/exp/Experiment.java new file mode 100644 index 0000000..ef52005 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/exp/Experiment.java @@ -0,0 +1,348 @@ +package ie.dcu.apps.ist.exp; + +import ie.dcu.eval.Evaluator; +import ie.dcu.apps.ist.*; +import ie.dcu.segment.Segmenter; + +import java.io.*; +import java.util.*; + +public class Experiment { + public static final int MAX_TASKS = 2500; + public static final int MAX_SEGMENTERS = 50; + public static final int MAX_EVALUATORS = 100; + + private String name; + private File dir; + private File outputFile; + private int time; + private List segmenters; + private List evaluators; + private List tasks; + private StorageSelection saveUserMasks; + private File saveUserMasksDir; + + Experiment() { + + } + + + public String getName() { + return name; + } + + + public File getDirectory() { + return dir; + } + + + public File getOutputFile() { + return outputFile; + } + + + public int getTime() { + return time; + } + + + public StorageSelection getStorageSelection() { + return saveUserMasks; + } + + + public File getStorageDirectory() { + return saveUserMasksDir; + } + + + public List getSegmenters() { + return Collections.unmodifiableList(segmenters); + } + + + public List getEvaluators() { + return Collections.unmodifiableList(evaluators); + } + + + public List getTasks() { + return Collections.unmodifiableList(tasks); + } + + + public boolean using(Segmenter segmenter) { + for (Segmenter s : segmenters) { + if (s.equals(segmenter)) { + return true; + } + } + return false; + } + + + public void load(File file) throws IOException, FormatException { + InputStream in = null; + try { + in = new FileInputStream(file); + load(in); + } finally { + if (in != null) { + in.close(); + } + } + } + + + public void load(InputStream in) throws IOException, FormatException { + + // Create properties object + Properties props = new Properties(); + props.load(in); + + // Load name + name = props.getProperty("name", "Experiment"); + + // Load directory + dir = getDir(props, "dir"); + + // Load output file + outputFile = getOutputFile(props); + + // Load task time + time = getTimeout(props, "time"); + + // Get save user masks selection + saveUserMasks = getStorageSelection(props, "save-user-masks"); + + // .. and directory + saveUserMasksDir = getUserMaskDir(props, "save-user-masks.dir"); + + // Load segmenters + segmenters = new ArrayList(); + for (int i = 1; i <= MAX_SEGMENTERS; i++) { + String key = "segmenters." + i; + String val = props.getProperty(key); + + if (val == null) { + break; + } + + Segmenter segmenter = findSegmenter(val); + if (segmenter != null) { + segmenters.add(segmenter); + } else { + exception("Segmenter not found: <%s>", val); + } + } + + // Load evaluators + evaluators = new ArrayList(); + for (int i = 1; i <= MAX_EVALUATORS; i++) { + String key = "evaluators." + i; + String val = props.getProperty(key); + + if (val == null) { + break; + } + + Evaluator evaluator = findEvaluator(val); + if (evaluator != null) { + evaluators.add(evaluator); + } else { + exception("Evaluator not found: <%s>", val); + } + } + + // Load tasks + tasks = new ArrayList(); + for (int i = 1; i <= MAX_TASKS; i++) { + + // Form keys + String imkey = String.format("task.%d.im", i); + String gtkey = String.format("task.%d.gt", i); + String desckey = String.format("task.%d.description", i); + + // Check if we're done + if (props.getProperty(imkey) == null) { + break; + } + + // Get image and ground truth file + File im = getFile(props, imkey); + File gt = getFile(props, gtkey); + + // Get description + String desc = getDescription(props, desckey); + + // Add task + tasks.add(new Task(im, gt, desc)); + } + } + + + private static StorageSelection getStorageSelection( + Properties props, String key + ) { + String prop = props.getProperty(key); + if (prop != null) { + StorageSelection selection = StorageSelection.parse(prop); + if (selection != null) { + return selection; + } + } + return StorageSelection.None; + } + + + private File getUserMaskDir(Properties props, String key) + throws FormatException { + + String fname = props.getProperty(key); + if (fname == null) { + fname = "user"; + } + + File file = new File(fname); + if (!file.isAbsolute()) { + file = new File(dir, fname); + } + + + if (!file.exists()) { + // Try and create it + if (!file.mkdirs()) { + String path = file.getAbsolutePath(); + exception("Couldn't create directory %s", path); + } + + } else if (!file.isDirectory()) { + String path = file.getAbsolutePath(); + exception("%s is not a directory", path); + } + + return file; + } + + + private static Segmenter findSegmenter(String name) { + return SegmenterRegistry.getInstance().find(name); + } + + + private static Evaluator findEvaluator(String name) { + return EvaluatorRegistry.getInstance().find(name); + } + + + private File getOutputFile(Properties props) { + String fname = props.getProperty("output", "output.txt"); + File file = new File(fname); + if (file.isAbsolute()) { + return file; + } + return new File(dir, fname); + } + + + + private static String getDescription(Properties props, String key) + throws FormatException { + + String desc = props.getProperty(key); + if (desc == null) { + exception("Expected description property for %s", key); + } + return desc; + } + + + private File getFile(Properties props, String key) + throws FormatException { + + String fname = props.getProperty(key); + + if (fname == null) { + exception("Expected file property for %s", key); + } + + File file = new File(fname); + if (file.isAbsolute()) { + if (file.isFile()) { + return file; + } + } + + file = new File(dir, fname); + if (!file.isFile()) { + exception("File not found %s", file.getAbsolutePath()); + } + + return file; + } + + + private static File getDir(Properties props, String key) + throws FormatException { + + String prop = props.getProperty(key); + if (prop == null) { + exception("Required directory element not found: %a",key); + } + + File file = new File(prop); + if (!file.isDirectory()) { + exception("%s is not a directory", prop); + } + + return file; + } + + + private static int getTimeout(Properties props, String key) + throws FormatException { + + String prop = props.getProperty(key, "120"); + try { + return Integer.parseInt(prop); + } catch (NumberFormatException ex) { + exception("%s is not an integer", key); + } + + return 0; + } + + + private static void exception(String format, Object ... args) + throws FormatException + { + throw new FormatException(String.format(format, args)); + } + + + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("name=<").append(name).append('>'); + sb.append(" dir=<").append(dir.getAbsolutePath()).append('>'); + sb.append(" output=<").append(outputFile.getAbsolutePath()).append('>'); + sb.append(" time=<").append(time).append('>'); + + // Evaluators + sb.append(" evaluators={ "); + for (Evaluator e : evaluators) { + sb.append(e.getName()).append(' '); + } + sb.append('}'); + + // Tasks + sb.append(" tasks={ "); + for (Task t : tasks) { + sb.append(t).append(' '); + } + sb.append('}'); + + return sb.toString(); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/exp/ExperimentFactory.java b/Annotation/src/ie/dcu/apps/ist/exp/ExperimentFactory.java new file mode 100644 index 0000000..802d14a --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/exp/ExperimentFactory.java @@ -0,0 +1,34 @@ +/** + * + */ +package ie.dcu.apps.ist.exp; + +import java.io.*; + +/** + * @author Kevin McGuinness + */ +public class ExperimentFactory { + private static ExperimentFactory instance; + + protected ExperimentFactory() { + + } + + public static ExperimentFactory getInstance() { + if (instance == null) { + instance = new ExperimentFactory(); + } + return instance; + } + + + public Experiment load(File file) + throws IOException, FormatException { + + Experiment ex = new Experiment(); + ex.load(file); + return ex; + } + +} diff --git a/Annotation/src/ie/dcu/apps/ist/exp/ExperimentManager.java b/Annotation/src/ie/dcu/apps/ist/exp/ExperimentManager.java new file mode 100644 index 0000000..b03a6f7 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/exp/ExperimentManager.java @@ -0,0 +1,217 @@ +package ie.dcu.apps.ist.exp; + +import ie.dcu.eval.Evaluator; +import ie.dcu.segment.SegmentationMask; +import ie.dcu.segment.SegmentationContext; +import ie.dcu.apps.ist.AppWindow; +import ie.dcu.apps.ist.actions.*; + +import java.io.*; +import java.util.List; + +public class ExperimentManager { + + private final AppWindow window; + + private Experiment experiment; + private SegmentationContext activeContext; + private SegmentationMask referenceMask; + private ExperimentResults results; + private List tasks; + private Task activeTask; + private int progress; + private boolean aborted; + + + public ExperimentManager(AppWindow window) { + this.window = window; + } + + + public void beginExperiment(Experiment ex) throws IOException { + experiment = ex; + tasks = experiment.getTasks(); + activeContext = null; + activeTask = null; + progress = 0; + results = new ExperimentResults(experiment.getOutputFile()); + results.beginDocument(); + results.beginExperiment(experiment); + } + + + public void endExperiment() throws IOException { + results.endExperiment(); + results.flush(); + results.close(); + } + + + public void abortExperiment() { + results.endExperiment(); + results.close(); + aborted = true; + } + + + public void beginTask() throws IOException { + if (isComplete()) { + throw new IllegalStateException(); + } + + // Set active task + activeTask = tasks.get(progress); + + // Load context into main window + loadContext(); + + // Load reference mask + loadReferenceMask(); + + // Write task header to results + results.beginTask(progress, activeTask); + } + + + public void endTask() throws IOException { + + try { + // Save final mask + StorageSelection ss = experiment.getStorageSelection(); + if (ss != StorageSelection.None) { + store(String.format("task-%d-final.png", progress)); + } + + } finally { + + activeTask = null; + activeContext = null; + progress++; + results.endTask(); + results.flush(); + } + } + + + public boolean isComplete() { + return tasks.size() == progress || aborted; + } + + + public Experiment getExperiment() { + return experiment; + } + + + public String getTaskDescription() { + return activeTask.getDescription(); + } + + + public Task getActiveTask() { + return activeTask; + } + + + public int getTaskCount() { + return tasks.size(); + } + + + public int getProgress() { + return progress; + } + + + public SegmentationContext getActiveContext() { + return activeContext; + } + + + public List getEvaluators() { + return experiment.getEvaluators(); + } + + + public File getImageFile() { + return activeTask.getImageFile(); + } + + + public SegmentationMask getCurrentMask() { + return activeContext.getMask(); + } + + + public SegmentationMask getReferenceMask() { + return referenceMask; + } + + + public void evaluate(int elapsed) { + + if (!getCurrentMask().isUnknown()) { + SegmentationMask im = getCurrentMask(); + SegmentationMask gt = getReferenceMask(); + + results.beginEvaluation(elapsed); + + for (Evaluator evaluator : experiment.getEvaluators()) { + // Execute evaluator + evaluator.run(im, gt); + + // Add results + addResults(evaluator); + } + + results.endEvaluation(); + } + } + + + public void store(int elapsed) throws IOException { + // Save current mask + if (!getCurrentMask().isUnknown()) { + // Only save non empty masks + StorageSelection ss = experiment.getStorageSelection(); + if (ss == StorageSelection.All) { + store(String.format("task-%d-time-%d.png", progress, elapsed)); + } + } + } + + + private void store(String name) throws IOException { + SegmentationMask im = getCurrentMask(); + File dir = experiment.getStorageDirectory(); + File file = new File(dir, name); + im.save(file); + } + + + private void addResults(Evaluator evaluator) { + String[] measures = evaluator.getMeasures(); + for (String measure : measures) { + double value = evaluator.getMeasure(measure); + results.addMeasure(measure, value); + } + } + + + private void loadReferenceMask() throws IOException { + referenceMask = new SegmentationMask(activeContext.getBounds()); + referenceMask.load(activeTask.getMaskFile()); + } + + + private void loadContext() throws IOException { + ActionManager actions = window.getActions(); + OpenAction action = actions.get(OpenAction.class); + + if (!action.open(getImageFile())) { + throw new IOException("Unable to load image file"); + } + + activeContext = window.getContext(); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/exp/ExperimentResults.java b/Annotation/src/ie/dcu/apps/ist/exp/ExperimentResults.java new file mode 100644 index 0000000..2f54026 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/exp/ExperimentResults.java @@ -0,0 +1,109 @@ +package ie.dcu.apps.ist.exp; + +import java.io.*; + +public class ExperimentResults { + private static final String XML_HEADER = + "%n%n"; + + private static final String BEGIN_EXPERIMENT_TAG = + "%n"; + + private static final String BEGIN_TASK_TAG = + " %n"; + + private static final String BEGIN_EVALUATION_TAG = + " %n"; + + private static final String MEASURE_TAG = + " %n"; + + private static final String END_EVALUATION_TAG = + " %n"; + + private static final String END_TASK_TAG = + " %n"; + + private static final String END_EXPERIMENT_TAG = + "%n"; + + + private final PrintStream out; + + + + ExperimentResults(File file) throws FileNotFoundException { + this(new FileOutputStream(file)); + } + + + ExperimentResults(OutputStream out) { + this.out = new PrintStream(new BufferedOutputStream(out)); + } + + + public void beginDocument() { + write(XML_HEADER); + } + + + public void beginExperiment(Experiment ex) { + String dir = ex.getDirectory().getAbsolutePath(); + write(BEGIN_EXPERIMENT_TAG, ex.getName(), ex.getTime(), dir); + } + + + public void beginTask(int idx, Task task) { + String im = task.getImageFile().getName(); + String gt = task.getMaskFile().getName(); + write(BEGIN_TASK_TAG, idx, im, gt); + } + + + public void beginEvaluation(int time) { + write(BEGIN_EVALUATION_TAG, time); + } + + + public void endEvaluation() { + write(END_EVALUATION_TAG); + } + + + public void addMeasure(String name, double value) { + write(MEASURE_TAG, name, value); + } + + + public void endTask() { + write(END_TASK_TAG); + } + + + public void endExperiment() { + write(END_EXPERIMENT_TAG); + } + + + public void endDocument() throws IOException { + flush(); + } + + + public void flush() throws IOException { + out.flush(); + if (out.checkError()) { + throw new IOException(); + } + } + + + public void close() { + out.close(); + } + + + private void write(String format, Object ... args) { + out.printf(format, args); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/exp/FormatException.java b/Annotation/src/ie/dcu/apps/ist/exp/FormatException.java new file mode 100644 index 0000000..8553f0d --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/exp/FormatException.java @@ -0,0 +1,48 @@ +/** + * + */ +package ie.dcu.apps.ist.exp; + +/** + * @author Kevin McGuinness + */ +public class FormatException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + + /** + * + */ + public FormatException() { + } + + + /** + * @param message + */ + public FormatException(String message) { + super(message); + } + + + /** + * @param cause + */ + public FormatException(Throwable cause) { + super(cause); + } + + + /** + * @param message + * @param cause + */ + public FormatException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/Annotation/src/ie/dcu/apps/ist/exp/StorageSelection.java b/Annotation/src/ie/dcu/apps/ist/exp/StorageSelection.java new file mode 100644 index 0000000..aeae41f --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/exp/StorageSelection.java @@ -0,0 +1,22 @@ +package ie.dcu.apps.ist.exp; + +/** + * Selection of what points in time to output the masks that + * the user has obtained so far in their interactions. + * + * @author Kevin McGuinness + */ +public enum StorageSelection { + All, + None, + Final; + + public static StorageSelection parse(String s) { + for (StorageSelection ss : values()) { + if (ss.toString().equalsIgnoreCase(s)) { + return ss; + } + } + return null; + } +}; diff --git a/Annotation/src/ie/dcu/apps/ist/exp/Task.java b/Annotation/src/ie/dcu/apps/ist/exp/Task.java new file mode 100644 index 0000000..754d4ed --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/exp/Task.java @@ -0,0 +1,39 @@ +package ie.dcu.apps.ist.exp; + +import java.io.*; + +public class Task { + + private final File imageFile; + private final File maskFile; + private final String description; + + + Task(File imFile, File gtFile, String desc) { + imageFile = imFile; + maskFile = gtFile; + description = desc; + } + + + public File getImageFile() { + return imageFile; + } + + + public File getMaskFile() { + return maskFile; + } + + + public String getDescription() { + return description; + } + + + public String toString() { + String im = imageFile.getAbsolutePath(); + String gt = maskFile.getAbsolutePath(); + return String.format("[ im=<%s> gt=<%s> desc=<%s> ]", im, gt, description); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/export/imagemap/AreaShape.java b/Annotation/src/ie/dcu/apps/ist/export/imagemap/AreaShape.java new file mode 100644 index 0000000..11fc339 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/export/imagemap/AreaShape.java @@ -0,0 +1,30 @@ +/** + * + */ +package ie.dcu.apps.ist.export.imagemap; + +/** + * The shape of the area tag for a HTML image map. + * + * @see HTML 4 DTD + * + * @author Kevin McGuinness + */ +public enum AreaShape { + Polygon("poly"), + Rectangle("rect"), + Circle("circle"); + + private String text; + + private AreaShape(String text) { + this.text = text; + } + + /** + * Returns the HTML shape attribute value. + */ + public String toString() { + return text; + } +} \ No newline at end of file diff --git a/Annotation/src/ie/dcu/apps/ist/export/imagemap/ExportException.java b/Annotation/src/ie/dcu/apps/ist/export/imagemap/ExportException.java new file mode 100644 index 0000000..51bf4c5 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/export/imagemap/ExportException.java @@ -0,0 +1,25 @@ +package ie.dcu.apps.ist.export.imagemap; + +/** + * Exception thrown when there is a problem producing the export. + * + * @author Kevin McGuinness + */ +public class ExportException extends Exception { + private static final long serialVersionUID = 1L; + + public ExportException() { + } + + public ExportException(String message) { + super(message); + } + + public ExportException(Throwable cause) { + super(cause); + } + + public ExportException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/export/imagemap/Exporter.java b/Annotation/src/ie/dcu/apps/ist/export/imagemap/Exporter.java new file mode 100644 index 0000000..09fafa1 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/export/imagemap/Exporter.java @@ -0,0 +1,189 @@ +package ie.dcu.apps.ist.export.imagemap; + +import ie.dcu.image.ContourTracer; +import ie.dcu.segment.SegmentationMask; +import ie.dcu.util.FileUtils; + +import java.awt.Polygon; +import java.awt.image.*; +import java.io.*; +import java.util.*; + +import javax.imageio.ImageIO; + +/** + * Exports HTML image maps from a segmentation mask and an image. + * + * @author Kevin McGuinness + */ +public class Exporter { + private final SegmentationMask mask; + private final BufferedImage image; + + private RolloverEffect effect; + private String htmlFile = "imagemap.html"; + private String imageFile = "image.png"; + private String imageName = "image"; + private String objectDescription = ""; + private String objectLink = ""; + private String title = ""; + private AreaShape exportShape = AreaShape.Polygon; + + public Exporter(BufferedImage image, SegmentationMask mask) { + this.image = image; + this.mask = mask; + } + + public RolloverEffect getEffect() { + return effect; + } + + public void setEffect(RolloverEffect effect) { + this.effect = effect; + } + + public String getHtmlFile() { + return htmlFile; + } + + public void setHtmlFile(String htmlFile) { + this.htmlFile = htmlFile; + } + + public String getImageFile() { + return imageFile; + } + + public void setImageFile(String imageFile) { + this.imageFile = imageFile; + } + + public String getImageName() { + return imageName; + } + + public void setImageName(String imageName) { + this.imageName = imageName; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getObjectDescription() { + return objectDescription; + } + + public void setObjectDescription(String description) { + this.objectDescription = description; + } + + public String getObjectLink() { + return objectLink; + } + + public void setObjectLink(String link) { + this.objectLink = link; + } + + public AreaShape getExportShape() { + return exportShape; + } + + public void setExportShape(AreaShape shape) { + this.exportShape = shape; + } + + public void export(File folder) throws IOException, ExportException { + ContourTracer tracer = new ContourTracer(mask, SegmentationMask.FOREGROUND); + List trace = tracer.trace(); + + if (trace.size() == 0) { + throw new ExportException("No objects found"); + } + + List preloads = getPreloads(trace); + + // Write image + ImageIO.write(image, "png", new File(folder, imageFile)); + + if (effect != null) { + int i = 1; + + // Generate effect images + for (Polygon object : trace) { + RenderedImage im = effect.createEffect(image, object); + File output = new File(folder, preloads.get(i++)); + ImageIO.write(im, "png", output); + } + } + + // Create image map + ImageMap map = new ImageMap(); + map.setImageHref(imageFile); + map.setImageName(imageName); + + // Add javascript preloads + for (String str : preloads) { + map.addPreload(str); + } + + // Add areas + int idx = 1; + for (Polygon polygon : trace) { + MapArea area = new MapArea(); + switch (exportShape) { + case Polygon: + area.setPolygon(polygon); + break; + case Rectangle: + area.setRect(polygon.getBounds()); + break; + case Circle: + // TODO: Implement circle! + + default: + area.setPolygon(polygon); + break; + } + + area.setAlt(objectDescription); + area.setHref(objectLink); + + if (effect != null) { + + + area.addAttr("onmouseover", + String.format("rollover(document.%s, image%s)", + imageName, idx++)); + area.addAttr("onmouseout", + String.format("rollover(document.%s, image0)", imageName)); + area.addAttr("title",getTitle()); + } + + map.addArea(area); + } + + map.exportToFile(new File(folder, htmlFile)); + } + + private List getPreloads(List trace) { + List preloads = new ArrayList(); + preloads.add(imageFile); + + if (effect != null) { + + String basename = FileUtils.removeExtension(imageFile); + for (int i = 0; i < trace.size(); i++) { + String filename = String.format("%s-%d.png", basename, i); + preloads.add(filename); + } + } + + return preloads; + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/export/imagemap/HtmlTag.java b/Annotation/src/ie/dcu/apps/ist/export/imagemap/HtmlTag.java new file mode 100644 index 0000000..7b0943e --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/export/imagemap/HtmlTag.java @@ -0,0 +1,80 @@ +package ie.dcu.apps.ist.export.imagemap; + +import java.util.HashMap; +import java.util.Map; + +/** + * Class used to generate HTML tags. + * + * @author Kevin McGuinness + */ +class HtmlTag { + final String name; + final Map attrs; + + HtmlTag(String name) { + this.name = name; + this.attrs = new HashMap(); + } + + HtmlTag attr(String name, String value) { + attrs.put(name, escape(value)); + return this; + } + + private static String escape(String value) { + return value.replaceAll("\"", "\\\\\""); + } + + static void indent(StringBuffer sb, int indent) { + for (int i = 0; i < indent; i++) { + sb.append(' '); + } + } + + void open(StringBuffer sb, int indent) { + open(sb, indent, false); + } + + void open(StringBuffer sb, int indent, boolean empty) { + + // Indent + indent(sb, indent); + + // Write start of tag + sb.append('<').append(name); + + // Write attributes + boolean first = true; + for (Map.Entry entry : attrs.entrySet()) { + + if (!first) { + sb.append('\n'); + indent(sb, indent + name.length() + 1); + } + + sb.append(' '); + sb.append(entry.getKey()); + sb.append('='); + sb.append('"'); + sb.append(entry.getValue()); + sb.append('"'); + + first = false; + } + + if (empty) { + sb.append('/'); + } + sb.append('>').append('\n'); + } + + void close(StringBuffer sb, int indent) { + indent(sb, indent); + sb.append('<'); + sb.append('/'); + sb.append(name); + sb.append('>'); + sb.append('\n'); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/export/imagemap/ImageMap.java b/Annotation/src/ie/dcu/apps/ist/export/imagemap/ImageMap.java new file mode 100644 index 0000000..4125ccf --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/export/imagemap/ImageMap.java @@ -0,0 +1,184 @@ +/** + * + */ +package ie.dcu.apps.ist.export.imagemap; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * Exports HTML image maps + * + * @author Kevin McGuinness + */ +public class ImageMap { + private static final String TEMPLATE_FILE = "template.html"; + + private String pageTitle; + private String imageName; + private String imageHref; + private String imageAlt; + private String mapName; + private final List areas; + private final List preloads; + + public ImageMap() { + // set defaults : + this.pageTitle = "Image Map"; + this.imageName = "image"; + this.imageHref = ""; + this.imageAlt = ""; + this.mapName = "imagemap"; + this.areas = new LinkedList(); + this.preloads = new LinkedList(); + } + + public String getPageTitle() { + return pageTitle; + } + + public void setPageTitle(String pageTitle) { + assert (pageTitle != null); + this.pageTitle = pageTitle; + } + + public String getImageName() { + return imageName; + } + + public void setImageName(String imageName) { + this.imageName = imageName; + } + + public String getImageHref() { + return imageHref; + } + + public void setImageHref(String imageHref) { + assert (imageHref != null); + this.imageHref = imageHref; + } + + public String getImageAlt() { + return imageAlt; + } + + public void setImageAlt(String imageAlt) { + assert (imageAlt != null); + this.imageAlt = imageAlt; + } + + public String getMapName() { + return mapName; + } + + public void setMapName(String mapName) { + assert (mapName != null); + this.mapName = mapName; + } + + public void addArea(MapArea area) { + areas.add(area); + } + + public List areas() { + return areas; + } + + public void addPreload(String preload) { + this.preloads.add(preload); + } + + public List preloads() { + return preloads; + } + + public String export() { + String template = loadTemplate(); + + // Create preloads buffer + StringBuffer preloads = new StringBuffer(); + int idx = 0; + for (String s : preloads()) { + HtmlTag.indent(preloads, 8); + preloads.append("var image").append(idx); + preloads.append(" = new Image()\n"); + HtmlTag.indent(preloads, 8); + preloads.append("image").append(idx); + preloads.append(".src = '").append(s).append("'\n"); + idx++; + } + + StringBuffer contents = new StringBuffer(); + for (MapArea area : areas) { + contents.append('\n'); + area.export(contents, 8); + } + + Map subs = new HashMap(); + subs.put("image-name", imageName); + subs.put("page-title", pageTitle); + subs.put("image-href", imageHref); + subs.put("image-alt", imageAlt); + subs.put("map-name", mapName); + subs.put("contents", contents.toString()); + subs.put("preloads", preloads.toString()); + + return substitute(template, subs); + } + + public void exportToFile(File file) throws IOException { + FileWriter writer = new FileWriter(file); + try { + writer.append(export()); + } finally { + writer.close(); + } + } + + private String substitute(String template, Map subs) { + // This could be more efficient.. + String result = template; + for (String key : subs.keySet()) { + String regex = String.format("\\$\\{%s\\}", key); + result = result.replaceAll(regex, subs.get(key)); + } + + return result; + } + + private String loadTemplate() { + BufferedReader reader = new BufferedReader(new InputStreamReader( + getClass().getResourceAsStream(TEMPLATE_FILE))); + + StringBuffer buff = new StringBuffer(); + + try { + String line; + while ((line = reader.readLine()) != null) { + buff.append(line).append('\n'); + } + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + try { + reader.close(); + } catch (IOException e) { + // Ignore + } + } + + return buff.toString(); + } + + public String toString() { + return export(); + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/export/imagemap/MapArea.java b/Annotation/src/ie/dcu/apps/ist/export/imagemap/MapArea.java new file mode 100644 index 0000000..2bc22b3 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/export/imagemap/MapArea.java @@ -0,0 +1,133 @@ +/** + * + */ +package ie.dcu.apps.ist.export.imagemap; + +import java.awt.Polygon; +import java.awt.Rectangle; +import java.net.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + + +public class MapArea { + + private String href; + private String alt; + private AreaShape shape; + private int[] coords; + private final Map attrs; + + public MapArea() { + href = ""; + alt = ""; + shape = AreaShape.Polygon; + coords = new int[0]; + attrs = new HashMap(); + } + + public void addAttr(String key, String value) { + attrs.put(key, value); + } + + public String getHref() { + return href; + } + + public void setHref(String href) { + this.href = href == null ? "" : href; + } + + public String getAlt() { + return alt; + } + + public void setAlt(String alt) { + this.alt = alt == null ? "" : alt; + } + + public AreaShape getShape() { + return shape; + } + + public void setShape(AreaShape shape) { + this.shape = shape == null ? AreaShape.Polygon : shape; + } + + public int[] getCoords() { + return coords; + } + + public void setCoords(int[] coords) { + this.coords = coords == null ? new int[0] : coords; + } + + public void setRect(Rectangle rect) { + setShape(AreaShape.Rectangle); + int[] coords = { + rect.x, + rect.y, + rect.x + rect.width, + rect.y + rect.height + }; + setCoords(coords); + } + + public void setCircle(int x, int y, int r) { + setShape(AreaShape.Circle); + int[] coords = { x, y, r }; + setCoords(coords); + } + + public void setPolygon(Polygon poly) { + setShape(AreaShape.Polygon); + int[] coords = new int[2*poly.npoints]; + for (int i = 0, j = 0; i < poly.npoints; i++) { + coords[j++] = poly.xpoints[i]; + coords[j++] = poly.ypoints[i]; + } + setCoords(coords); + } + + public void export(StringBuffer sb, int indent) { + String encodedHREF = href; + if (href.length() != 0) { + try { + URI uri = new URI(href); + URL url = uri.toURL(); + encodedHREF = url.toString(); + } catch (URISyntaxException e) { + // Ignore exceptions, the href string will be used instead + } catch (MalformedURLException e) { + // Ignore exceptions, the href string will be used instead + } + } + + HtmlTag tag = new HtmlTag("area"); + tag + .attr("href", encodedHREF) + .attr("alt", alt) + .attr("shape", shape.toString()) + .attr("coords", getCoordsString()); + + for (Entry entry : attrs.entrySet()) { + tag.attr(entry.getKey(), entry.getValue()); + } + + tag.open(sb, indent, true); + } + + public String getCoordsString() { + StringBuffer sb = new StringBuffer(); + boolean first = true; + for (int coord : coords) { + if (!first) { + sb.append(','); + } + sb.append(coord); + first = false; + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/Annotation/src/ie/dcu/apps/ist/export/imagemap/RolloverEffect.java b/Annotation/src/ie/dcu/apps/ist/export/imagemap/RolloverEffect.java new file mode 100644 index 0000000..8e5ea2b --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/export/imagemap/RolloverEffect.java @@ -0,0 +1,191 @@ +package ie.dcu.apps.ist.export.imagemap; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.geom.Area; +import java.awt.image.BufferedImage; +import java.awt.image.RenderedImage; + +/** + * The roll-over effect for the image map. + * + * @author Kevin McGuinness + */ +public abstract class RolloverEffect { + + public abstract RenderedImage createEffect(Image image, Polygon object); + + public static RolloverEffect darkenBackground(float alpha) { + return new DarkenBackground(alpha); + } + + public static RolloverEffect darkenBackground() { + return new DarkenBackground(); + } + + public static RolloverEffect brightenForeground(float alpha) { + return new BrightenForeground(alpha); + } + + public static RolloverEffect brightenForeground() { + return new BrightenForeground(); + } + + public static RolloverEffect outlineObject() { + return new OutlineObject(); + } + + public static RolloverEffect outlineObject(Color color) { + return new OutlineObject(color); + } + + public static RolloverEffect outlineObject(Color color, Stroke stroke) { + return new OutlineObject(color, stroke); + } + + public static class DarkenBackground extends RolloverEffect { + + private float alpha = 0.5f; + + public DarkenBackground() { + + } + + public DarkenBackground(float alpha) { + this.alpha = alpha; + } + + public float getAlpha() { + return alpha; + } + + public void setAlpha(float alpha) { + this.alpha = alpha; + } + + @Override + public RenderedImage createEffect(Image image, Polygon object) { + int width = image.getWidth(null); + int height = image.getHeight(null); + BufferedImage im = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + + Area area = new Area(new Rectangle(0,0,width,height)); + area.subtract(new Area(object)); + + Graphics g = im.getGraphics(); + if (g instanceof Graphics2D) { + Graphics2D g2 = (Graphics2D) g; + g2.drawImage(image, 0, 0, null); + g2.setColor(new Color(0,0,0,alpha)); + g2.fill(area); + } + + return im; + } + } + + public static class BrightenForeground extends RolloverEffect { + + private float alpha = 0.5f; + + public BrightenForeground() { + + } + + public BrightenForeground(float alpha) { + this.alpha = alpha; + } + + public float getAlpha() { + return alpha; + } + + public void setAlpha(float alpha) { + this.alpha = alpha; + } + + @Override + public RenderedImage createEffect(Image image, Polygon object) { + int width = image.getWidth(null); + int height = image.getHeight(null); + BufferedImage im = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + + Graphics g = im.getGraphics(); + if (g instanceof Graphics2D) { + Graphics2D g2 = (Graphics2D) g; + g2.drawImage(image, 0, 0, null); + g2.setColor(new Color(1,1,1,alpha)); + g2.fill(object); + } + + return im; + } + } + + public static class OutlineObject extends RolloverEffect { + + private Color color = Color.white; + private Stroke stroke = new BasicStroke(2.0f, + BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + + public OutlineObject() { + + } + + public OutlineObject(Color color) { + this.color = color; + } + + public OutlineObject(Color color, Stroke stroke) { + this.color = color; + this.stroke = stroke; + } + + public Color getColor() { + return color; + } + + public void setColor(Color color) { + this.color = color; + } + + public Stroke getStroke() { + return stroke; + } + + public void setStroke(Stroke stroke) { + this.stroke = stroke; + } + + @Override + public RenderedImage createEffect(Image image, Polygon object) { + int width = image.getWidth(null); + int height = image.getHeight(null); + BufferedImage im = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + + Graphics g = im.getGraphics(); + if (g instanceof Graphics2D) { + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2.drawImage(image, 0, 0, null); + g2.setColor(color); + g2.setStroke(stroke); + g2.draw(object); + } + + return im; + } + } +} + diff --git a/Annotation/src/ie/dcu/apps/ist/export/imagemap/template.html b/Annotation/src/ie/dcu/apps/ist/export/imagemap/template.html new file mode 100644 index 0000000..159d2a1 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/export/imagemap/template.html @@ -0,0 +1,38 @@ + + + + + + + + ${page-title} + + + + + + + ${image-alt} + + + +${contents} + + + \ No newline at end of file diff --git a/Annotation/src/ie/dcu/apps/ist/recent/RecentFiles.java b/Annotation/src/ie/dcu/apps/ist/recent/RecentFiles.java new file mode 100644 index 0000000..16ef717 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/recent/RecentFiles.java @@ -0,0 +1,234 @@ +package ie.dcu.apps.ist.recent; + +import java.io.*; +import java.util.*; +import java.util.logging.*; + +/** + * Class for managing a recent documents list. + * + * @author Kevin McGuinness + */ +public class RecentFiles implements Iterable { + public static final int DEFAULT_CAPACITY = 10; + + + private final LinkedList history; + private final List listeners; + private final File store; + private int capacity; + + + public RecentFiles(File store) { + + // Check the store is ok + checkValid(store); + + // Construct + this.history = new LinkedList(); + this.listeners = new LinkedList(); + this.store = store; + this.capacity = DEFAULT_CAPACITY; + + // Add a vm shutdown hook + addShutdownHook(); + } + + + public void setCapacity(int capacity) { + + // Check positive + if (capacity < 0) { + throw new IllegalArgumentException("capacity < 0"); + } + + if (this.capacity != capacity) { + this.capacity = capacity; + + // Capacity may have reduced + boolean reduced = history.size() > capacity; + while (history.size() > capacity) { + history.removeLast(); + } + + // Fire change + if (reduced) { + fireHistoryChanged(); + } + } + } + + + public int getCapacity() { + return capacity; + } + + + public void add(File file) { + if (!history.contains(file)) { + history.addFirst(file); + + // Check if we have exceeded capacity + if (history.size() > capacity) { + history.removeLast(); + } + + // Fire change + fireHistoryChanged(); + } + } + + + public void clear() { + if (!empty()) { + history.clear(); + fireHistoryChanged(); + } + } + + + public List files() { + return Collections.unmodifiableList(history); + } + + + public Iterator iterator() { + return files().iterator(); + } + + + public boolean empty() { + return history.isEmpty(); + } + + + public void load() throws IOException { + if (!store.exists()) { + // Create an empty store + store.createNewFile(); + } + + BufferedReader in = null; + try { + read(in = new BufferedReader(new FileReader(store))); + + } finally { + in.close(); + } + } + + + public void store() throws IOException { + PrintWriter out = null; + try { + write(out = new PrintWriter(store)); + + } finally { + out.close(); + } + } + + + public void addListener(RecentFilesListener rfl) { + listeners.add(rfl); + } + + + public void removeListener(RecentFilesListener rfl) { + listeners.remove(rfl); + } + + + protected static Logger getLogger() { + return Logger.getLogger(RecentFiles.class.getName()); + } + + + private void shutdown() { + try { + store(); + } catch (IOException e) { + getLogger().warning("Error writing recent documents to store: " + e); + } + } + + + private void fireHistoryChanged() { + RecentFilesEvent evt = null; + for (RecentFilesListener listener : listeners) { + if (evt == null) { + evt = new RecentFilesEvent(this); + listener.historyChanged(evt); + } + } + } + + + private void checkValid(File store) { + if (store == null) { + throw new IllegalArgumentException("store cannot be null"); + } + + if (store.isDirectory()) { + throw new IllegalArgumentException("store cannot be a directory"); + } + + if (store.isFile()) { + if (!store.canWrite()) { + throw new IllegalArgumentException("store not writable"); + } + } + } + + + private void addShutdownHook() { + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + shutdown(); + } + }); + } + + + private void read(BufferedReader in) throws IOException { + + // Remember old history to check for changes + LinkedList old = new LinkedList(history); + + // Clear history if not empty + history.clear(); + + // Read files (discarding no longer existent ones) + String line; + while ((line = in.readLine()) != null) { + + // Stop when full + if (history.size() == capacity) { + break; + } + + File file = new File(line); + if (file.exists()) { + history.add(file); + } + } + + // Fire change if a change occurred + if (!history.equals(old)) { + fireHistoryChanged(); + } + } + + + private void write(PrintWriter out) throws IOException { + for (File file : history) { + String path = file.getAbsolutePath(); + out.println(path); + } + + // Check for errors + if (out.checkError()) { + throw new IOException("Error writing to file"); + } + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/recent/RecentFilesEvent.java b/Annotation/src/ie/dcu/apps/ist/recent/RecentFilesEvent.java new file mode 100644 index 0000000..8b0932e --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/recent/RecentFilesEvent.java @@ -0,0 +1,17 @@ +package ie.dcu.apps.ist.recent; + +import java.util.*; + +public class RecentFilesEvent extends EventObject { + private static final long serialVersionUID = 1L; + + + public RecentFilesEvent(RecentFiles source) { + super(source); + } + + + public RecentFiles getList() { + return (RecentFiles) source; + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/recent/RecentFilesListener.java b/Annotation/src/ie/dcu/apps/ist/recent/RecentFilesListener.java new file mode 100644 index 0000000..8d50258 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/recent/RecentFilesListener.java @@ -0,0 +1,8 @@ +package ie.dcu.apps.ist.recent; + +import java.util.*; + +public interface RecentFilesListener extends EventListener { + + public void historyChanged(RecentFilesEvent evt); +} diff --git a/Annotation/src/ie/dcu/apps/ist/views/ExperimentPanel.java b/Annotation/src/ie/dcu/apps/ist/views/ExperimentPanel.java new file mode 100644 index 0000000..94dc2e3 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/views/ExperimentPanel.java @@ -0,0 +1,547 @@ +/** + * + */ +package ie.dcu.apps.ist.views; + +import ie.dcu.apps.ist.AppWindow; +import ie.dcu.apps.ist.event.*; +import ie.dcu.apps.ist.exp.*; +import ie.dcu.apps.ist.widgets.SwtTimer; +import ie.dcu.segment.annotate.*; + +import java.io.IOException; +import java.util.Properties; +import java.util.logging.*; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +/** + * @author Kevin McGuinness + */ +public class ExperimentPanel extends Composite { + + // Some property keys + private static final String DESCRIPTION_TITLE + = "description.title"; + + private static final String TIMEOUT_MESSAGE + = "timeout-message"; + + private static final String EXPERIMENT_COMPLETE_MESSAGE + = "experiment-complete-message"; + + // Type of button in use + private static enum ButtonType { Start, Finish }; + + // App window and experiment + private final AppWindow window; + private final Experiment experiment; + private final Logger log; + + // Controls + private final Group group; + private final Button button; + private final SwtTimer timer; + private final Text text; + + // Shell if the panel is inside a shell + private Shell shell; + + // Experiment manager + private final ExperimentManager manager; + private final EvaluationListener evaluator; + + + public ExperimentPanel(AppWindow window, Composite parent, int style) { + super(parent, style); + + // Set app window + this.window = window; + this.experiment = window.getExperiment(); + this.log = Logger.getLogger("Experiment"); + + + // Create controls + timer = new SwtTimer(this, SWT.NONE); + group = new Group(this, SWT.DEFAULT); + button = new Button(this, SWT.PUSH); + text = new Text(group, SWT.READ_ONLY | SWT.WRAP); + + // Create manager and evaluator + manager = new ExperimentManager(window); + evaluator = new EvaluationListener(manager, timer); + + // Setup controls + setupControls(); + layoutControls(); + addListeners(); + + // Begin experiment + beginExperiment(); + } + + + public static void open(AppWindow win) { + Shell app = win.getShell(); + + // Style bits + int style = SWT.MODELESS | SWT.RESIZE | SWT.BORDER | SWT.TITLE | SWT.CLOSE; + + // Construct shell + Shell shell = new Shell(app, style); + + // Determine shell bounds + Rectangle bounds = new Rectangle(0,0,180,280); + + // Move shell to an appropriate place (right of app window) + Rectangle rect = app.getBounds(); + bounds.x = rect.x + rect.width; + bounds.y = rect.y + rect.height / 2 - bounds.height / 2; + + // Move back if outside the screen + Rectangle screen = shell.getDisplay().getBounds(); + if (bounds.x + bounds.width > screen.width) { + bounds.x -= bounds.x + bounds.width - screen.width; + } + + // Set bounds + shell.setBounds(bounds); + + // Set layout + shell.setLayout(new FillLayout()); + + // Create experiment panel + final ExperimentPanel panel + = new ExperimentPanel(win, shell, SWT.NONE); + + panel.shell = shell; + panel.updateTitle(); + + // Add shell close button listener + shell.addShellListener(new ShellAdapter() { + public void shellClosed(ShellEvent e) { + if (!panel.manager.isComplete()) { + e.doit = panel.cancelExperiment(); + } + } + }); + + // Open experiment panel + shell.open(); + } + + + private void setupControls() { + group.setText(property(DESCRIPTION_TITLE)); + text.setEnabled(false); + enableButton(null); + } + + + private void layoutControls() { + GridLayout gl; + GridData gd; + + // Setup layout manager for this + gl = new GridLayout(); + gl.marginTop = 5; + gl.verticalSpacing = 5; + this.setLayout(gl); + + // Setup layout manager for group + gl = new GridLayout(); + group.setLayout(gl); + + // Layout timer + gd = new GridData(SWT.FILL, SWT.FILL, true, false); + timer.setLayoutData(gd); + + // Layout group + gd = new GridData(SWT.FILL, SWT.FILL, true, true); + group.setLayoutData(gd); + + // Layout button + gd = new GridData(SWT.FILL, SWT.FILL, true, false); + button.setLayoutData(gd); + + // Layout text + gd = new GridData(SWT.FILL, SWT.FILL, true, true); + text.setLayoutData(gd); + } + + + private void addListeners() { + button.addListener(SWT.Selection, buttonListener); + timer.addTimeoutListener(timeListener); + } + + + /** + * Function to call if something goes wrong with the experiment. Shows an + * error message and gracefully returns the application to normal mode. + * + * @param reason + * Short description of the problem. + */ + private void abortExperiment(String reason) { + timer.clear(); + evaluator.detach(); + + // Show abort message + error("Aborting experiment!%n%s", reason); + + // Tell manager of abort + manager.abortExperiment(); + + // Exit experiment mode + exitExperimentMode(); + } + + + /** + * Does what is necessary to exit experiment mode. + */ + private void exitExperimentMode() { + // Remove experiment view + window.setExperiment(null); + + // Re-enable interactions + window.getView().setEnabled(true); + + // Kill the shell + closeShell(); + } + + + /** + * Closes the encompassing (non-application) shell, if any. + */ + private void closeShell() { + if (shell != null) { + shell.close(); + shell.dispose(); + shell = null; + } + } + + + private boolean cancelExperiment() { + // Make sure the user knows what they're doing + boolean cancel = MessageDialog.openQuestion(window.getShell(), "Confirm", + "Are you sure you want to cancel the experiment?"); + + if (cancel) { + // Guess we better do what the user says, grumble grumble :-/ + timer.clear(); + evaluator.detach(); + manager.abortExperiment(); + window.setExperiment(null); + window.getView().setEnabled(true); + } + + return cancel; + } + + + /** + * Start the experiment. + */ + private void beginExperiment() { + try { + manager.beginExperiment(experiment); + + } catch (IOException e) { + log.log(Level.SEVERE, "Error starting experiment", e); + abortExperiment(e.getMessage()); + } + + // Begin first task + beginTask(); + } + + + /** + * Finish the experiment. + */ + private void endExperiment() { + try { + manager.endExperiment(); + + } catch (IOException e) { + log.log(Level.SEVERE, "Error ending experiment", e); + abortExperiment(e.getMessage()); + } + + // Tell user experiment is complete + notifyExperimentComplete(); + + // Stop experiment mode + exitExperimentMode(); + } + + + /** + * Load the task. + */ + private void beginTask() { + + // Set timer + timer.set(experiment.getTime()); + + // Begin task + try { + manager.beginTask(); + } catch (IOException e) { + log.log(Level.SEVERE, "Error starting task", e); + abortExperiment(e.getMessage()); + } + + // Disable interactions + window.getView().setEnabled(false); + + // Update description + text.setText(manager.getTaskDescription()); + + // Update title text + updateTitle(); + + // Setup start button + enableButton(ButtonType.Start); + + // Attach evaluator + evaluator.attach(); + } + + + private void updateTitle() { + if (shell != null) { + int ntasks = manager.getTaskCount(); + int progress = manager.getProgress(); + shell.setText(String.format("Task [%d/%d]", progress+1, ntasks)); + } + } + + + /** + * Start the task. + */ + private void startTask() { + + // Enable interactions + window.getView().setEnabled(true); + + // Start clock + timer.start(); + + // Enable finish button + enableButton(ButtonType.Finish); + } + + + /** + * End the task. + */ + private void endTask() { + // Detach evaluator + evaluator.detach(); + + // Evaluate final result + manager.evaluate(timer.getElapsed()); + + // End task + try { + manager.endTask(); + } catch (IOException e) { + log.log(Level.SEVERE, "Error ending task", e); + abortExperiment(e.getMessage()); + } + + // Stop and clear clock + timer.clear(); + } + + + /** + * End the current task and start the next. + * End the experiment if finished. + */ + private void nextTask() { + endTask(); + if (manager.isComplete()) { + endExperiment(); + } else { + beginTask(); + } + } + + + private void enableButton(ButtonType type) { + if (type != null) { + String name = type.toString().toLowerCase(); + button.setText(property("button.text." + name)); + button.setData(type); + button.setEnabled(true); + button.setFocus(); + } else { + button.setText(property("button.text.start")); + button.setEnabled(false); + button.setData(null); + } + } + + + private ButtonType getEnabledButton() { + return (ButtonType) button.getData(); + } + + + private void handleButtonClicked() { + ButtonType btn = getEnabledButton(); + switch (btn) { + case Start: + startTask(); + break; + case Finish: + // Prevent clicking finish by accident + if (manager.getActiveContext().getAnnotations().count() == 0) { + getDisplay().beep(); + } else { + nextTask(); + } + break; + } + } + + + private void handleTimeout() { + // Finish task + endTask(); + + // Tell user + notifyTimeoutOccurred(); + + // Next task + if (manager.isComplete()) { + endExperiment(); + } else { + beginTask(); + } + } + + + private void notifyExperimentComplete() { + message(EXPERIMENT_COMPLETE_MESSAGE); + } + + + private void notifyTimeoutOccurred() { + // BEEP BEEP!! time up :-) + getDisplay().beep(); + message(TIMEOUT_MESSAGE); + } + + + private void message(String key) { + Shell main = window.getShell(); + MessageDialog.openInformation(main, "Information", property(key)); + } + + + private void error(String message, Object ... args) { + Shell main = window.getShell(); + MessageDialog.openError(main, "Error", String.format(message, args)); + } + + + private String property(String key) { + return property(key, key); + } + + + private String property(String key, String def) { + Properties p = window.getProperties(); + return p.getProperty(String.format("ExperimentPanel.%s", key), def); + } + + + private final Listener buttonListener = new Listener() { + public void handleEvent(Event event) { + handleButtonClicked(); + } + }; + + + private final TimeoutListener timeListener = new TimeoutListener() { + public void timeoutOccured(TimeoutEvent evt) { + handleTimeout(); + } + }; +} + + +class EvaluationListener implements AnnotationListener { + private final ExperimentManager manager; + private final SwtTimer timer; + private final Logger log; + + public EvaluationListener(ExperimentManager manager, SwtTimer timer) { + this.manager = manager; + this.timer = timer; + this.log = Logger.getLogger("Experiment"); + } + + + public void attach() { + manager.getActiveContext().addAnnotationListener(this); + } + + + public void detach() { + manager.getActiveContext().removeAnnotationListener(this); + } + + + private void annotationsChanged(AnnotationEvent e) { + // Return if there is nothing to evaluate yet + if (e.manager.count() == 0) { + return; + } + + // Time the change occurred + int time = timer.getElapsed(); + manager.evaluate(time); + + // Store if necessary + try { + manager.store(time); + } catch (IOException ex) { + log.log(Level.SEVERE, "Error storing intermediate segmentation mask", e); + } + } + + + public void annotationPerformed(AnnotationEvent e) { + annotationsChanged(e); + } + + + public void annotationRedone(AnnotationEvent e) { + annotationsChanged(e); + } + + + public void annotationUndone(AnnotationEvent e) { + annotationsChanged(e); + } + + + public void annotationsCleared(AnnotationEvent e) { + annotationsChanged(e); + } +} + diff --git a/Annotation/src/ie/dcu/apps/ist/views/SegmentationView.java b/Annotation/src/ie/dcu/apps/ist/views/SegmentationView.java new file mode 100644 index 0000000..5633d7d --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/views/SegmentationView.java @@ -0,0 +1,1074 @@ +package ie.dcu.apps.ist.views; + + +import ie.dcu.apps.ist.PainterRegistry; +import ie.dcu.apps.ist.event.*; +import ie.dcu.apps.ist.widgets.*; +import ie.dcu.segment.*; +import ie.dcu.segment.annotate.*; +import ie.dcu.segment.options.SegmenterOptionDialog; +import ie.dcu.segment.painters.SegmentationPainter; +import ie.dcu.swt.*; +import ie.dcu.swt.event.*; + +import java.lang.reflect.InvocationTargetException; +import java.net.*; +import java.util.Properties; +import java.util.logging.*; +import java.io.*; +import org.json.*; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.action.*; +import org.eclipse.jface.operation.*; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +public class SegmentationView extends Composite { + // Logger + private static final Logger log = Logger.getLogger(SegmentationView.class.getName()); + + + // Segmentation view properties + private final Properties props; + + + // Houses various painters + private final PainterRegistry painters; + + + // View handling annotations + private final AnnotatedImageControl view; + + + // Left and right tool bar + private final ToolBar bar1, bar2, bar3; + + private final Button assign; + + //private final StyledText text; + + // Control to change brush size + private final BrushControl brushControl; + + + // Handles various events + private final EventHandler eventHandler; + + + // Proxy object to catch and log exceptions thrown by the segmentation + // algorithm, without crashing the application. + private RobustSegmenterProxy segmenterProxy; + + // Auto segment on update flag + private boolean auto = true; + + // Combo box housing the selectable views + private Combo combo; + + public static Combo comboLabel; + + // Current segmentation tool + private Segmenter segmenter; + + + // Context to run the segmentation in, (may be null) + private IRunnableContext runnableContext; + + + // Flag to indicate that the runnable context blocks when fork is true + private boolean blocksOnFork; + + + public enum Tool { + Foreground, + Background, + ZoomIn, + ZoomOut, + ZoomOriginal, + ZoomBestFit, + Repaint, + Undo, + Redo, + Clear, + SetBrushSize, + AutoApply, + Apply, + SetPainter, + SetLabel, + AssignButton, + SegmenterOptions; + + private ToolAction action; + }; + + + public SegmentationView(Properties props, Composite parent, int style) { + super(parent, style); + this.props = props; + + painters = new PainterRegistry(); + bar1 = new ToolBar(this, SWT.RIGHT | SWT.FLAT); + bar2 = new ToolBar(this, SWT.RIGHT | SWT.FLAT); + bar3 = new ToolBar(this, SWT.RIGHT | SWT.FLAT); + assign = new Button(bar3, SWT.PUSH); + view = new AnnotatedImageControl(this, SWT.BORDER); + brushControl = new BrushControl(getShell(), SWT.BORDER); + eventHandler = new EventHandler(); + segmenterProxy = new RobustSegmenterProxy(); + + init(); + } + + + /** + * Initialize. + */ + private void init() { + initTools(); + createToolbar1(); + createToolbar2(); + createToolbar3(); + layoutControls(); + updatePainters(); + addListeners(); + updateToolStates(); + } + + + private void initTools() { + for (Tool t : Tool.values()) { + if (t.action == null) { + new ToolAction(t); + } + } + } + + + private void addListeners() { + brushControl.addSelectionListener(eventHandler); + view.addContextChangeListener(eventHandler); + view.addZoomListener(eventHandler); + addDisposeListener(eventHandler); + } + + + private void createToolbar1() { + ToolBarManager m = new ToolBarManager(bar1); + m.add(getAction(Tool.Foreground)); + m.add(getAction(Tool.Background)); + m.add(new Separator()); + m.add(getAction(Tool.ZoomIn)); + m.add(getAction(Tool.ZoomOut)); + m.add(getAction(Tool.ZoomOriginal)); + m.add(getAction(Tool.ZoomBestFit)); + m.add(new Separator()); + m.add(getAction(Tool.Repaint)); + m.add(getAction(Tool.Undo)); + m.add(getAction(Tool.Redo)); + m.add(getAction(Tool.Clear)); + m.add(new Separator()); + m.add(getAction(Tool.SetBrushSize)); + m.add(new Separator()); + m.add(getAction(Tool.AutoApply)); + m.add(getAction(Tool.Apply)); + m.add(getAction(Tool.SegmenterOptions)); + m.update(true); + } + + + private void createToolbar2() { + SwtUtils.addLabel(bar2, getAction(Tool.SetPainter).getText()); + combo = SwtUtils.addCombo(bar2, 115, SWT.READ_ONLY); + combo.setToolTipText( getAction(Tool.SetPainter).getToolTipText()); + combo.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + execute(Tool.SetPainter, null); + } + }); + bar2.pack(); + } + /** + * Third tool bar for holding the Annotate Combo box. + */ + private void createToolbar3() { + SwtUtils.addLabel(bar3, getAction(Tool.SetLabel).getText()); + comboLabel = SwtUtils.addCombo(bar3, 130, SWT.SIMPLE); + comboLabel.setToolTipText( getAction(Tool.SetLabel).getToolTipText()); + comboLabel.addKeyListener(new KeyListener() { + @Override + public void keyReleased(KeyEvent e) { + comboLabel.remove(0,comboLabel.getItemCount()-1); + setLabel(comboLabel.getText()); + Display.getCurrent().asyncExec(new Runnable() { + public void run() { + comboLabel.setText(comboLabel.getText()); + comboLabel.forceFocus(); + } + }); + } + @Override + public void keyPressed(KeyEvent arg0) { + // TODO Auto-generated method stub + } + }); + ToolItem item = new ToolItem(bar3, SWT.SEPARATOR); + assign.setText("Assign"); + item.setWidth(50); + item.setControl(assign); + assign.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent arg0) { + String lab = null; + if(comboLabel.getText().indexOf('{') != -1) + { + lab = comboLabel.getText().substring(0,comboLabel.getText().indexOf('{')-1); + } + else + { + lab = comboLabel.getText(); + } + System.out.println("selected"+lab); + execute(Tool.AssignButton, null); + } + @Override + public void widgetDefaultSelected(SelectionEvent arg0) { + // TODO Auto-generated method stub + } + }); + bar3.pack(); + } + + + private void layoutControls() { + GridLayout layout = new GridLayout(3, false); + layout.marginHeight = 1; + layout.marginWidth = 2; + layout.horizontalSpacing = -1; // zero leaves 1 pixel gap + layout.verticalSpacing = 1; + setLayout(layout); + + Point sz1 = bar1.computeSize(SWT.DEFAULT, SWT.DEFAULT); + Point sz2 = bar2.computeSize(SWT.DEFAULT, SWT.DEFAULT); + + int heightHint = Math.max(sz1.y, sz2.y); + + // Layout toolbar 1 + GridData gd = new GridData(); + gd.grabExcessHorizontalSpace = true; + gd.horizontalAlignment = SWT.FILL; + gd.heightHint = heightHint; + bar1.setLayoutData(gd); + + // Layout toolbar 2 + gd = new GridData(); + gd.horizontalAlignment = SWT.FILL; + gd.heightHint = heightHint; + bar2.setLayoutData(gd); + + // Layout view + gd = new GridData(); + gd.verticalIndent = 2; + gd.horizontalSpan = 3; + gd.grabExcessHorizontalSpace = true; + gd.grabExcessVerticalSpace = true; + gd.horizontalAlignment = SWT.FILL; + gd.verticalAlignment = SWT.FILL; + view.setLayoutData(gd); + } + + + private void updatePainters() { + combo.removeAll(); + boolean first = true; + for (SegmentationPainter p : painters.values()) { + combo.add(p.getName()); + if (first) { + combo.setText(p.getName()); + first = false; + } + } + } + + + public void setSegmenter(Segmenter segmenter) { + if (this.segmenter != segmenter) { + SegmentationContext ctx = view.getContext(); + + if (this.segmenter != null && ctx != null) { + // Finish old segmentation + segmenterProxy.finish(ctx); + + // Remove old segmenter + this.segmenter = null; + } + + // Set new segmenter + this.segmenter = segmenter; + + // Initialize a new segmentation + start(ctx); + + // Update enabled buttons + updateToolStates(); + } + } + + + public Segmenter getSegmenter() { + return segmenter; + } + + + public void setContext(SegmentationContext ctx) { + + // context change handler handles initialization etc. + // of segmenter and context + view.setContext(ctx); + } + + + public SegmentationContext getContext() { + return view.getContext(); + } + + + public void setAnnotationType(AnnotationType type) { + view.setAnnotationType(type); + } + + + public Canvas getCanvas() { + return view.getCanvas(); + } + + + public ImageControl getImageControl() { + return view.getImageControl(); + } + + + public void zoomIn() { + view.zoomIn(); + } + + + public void zoomOut() { + view.zoomOut(); + } + + + public void zoomOriginal() { + view.zoomOriginal(); + } + + + public void zoomBestFit() { + view.zoomBestFit(); + } + + + public void repaint() { + view.repaint(); + } + + + public void undo() { + view.undo(); + } + + + public void redo() { + view.redo(); + } + + + public void clear() { + view.clear(); + } + + + public void setBrushSize(int size) { + view.setLineWidth(size); + } + + + public void setPainter(SegmentationPainter painter) { + view.setPainter(painter); + combo.setText(painter.getName()); + } + + + public SegmentationPainter getPainter() { + return view.getPainter(); + } + + + public void setAutoApply(boolean checked) { + if (!this.auto && checked) { + // Going from off to on, resegment now + apply(); + } + this.auto = checked; + } + + + public boolean isAutoApply() { + return this.auto; + } + + + public boolean canZoomIn() { + return view.canZoomIn(); + } + + + public boolean canZoomOut() { + return view.canZoomOut(); + } + + + public boolean canZoomOriginal() { + return view.canZoomOriginal(); + } + + + public boolean canZoomBestFit() { + return view.canZoomBestFit(); + } + + + public boolean canUndo() { + return view.canUndo(); + } + + + public boolean canRedo() { + return view.canRedo(); + } + + + public boolean canClear() { + return view.canClear(); + } + + + public boolean canShowOptions() { + if (hasSegmenter()) { + return segmenter.getOptions().size() > 0; + } + return false; + } + + + public Action getAction(Tool t) { + return t.action; + } + + + public void showSegmenterOptions() { + if (canShowOptions()) { + SegmenterOptionDialog dialog = + new SegmenterOptionDialog(getShell(), segmenter); + + int result = dialog.open(); + switch (result) { + case SegmenterOptionDialog.OK: + // Re-segment + apply(); + } + } + } + + + public boolean hasSegmenter() { + return segmenter != null; + } + + + public void performSegmentation(AnnotationEvent e, SegmentationContext ctx) { + + if (runnableContext == null) { + segment(e, ctx); + } else { + segmentWithRunnableContext(e, ctx); + } + + // Repaint everything + repaint(); + + } + + + public void setRunnableContext(IRunnableContext context, boolean blocksOnFork) { + runnableContext = context; + this.blocksOnFork = blocksOnFork; + } + + + public void addContextChangeListener(ContextChangeListener listener) { + view.addContextChangeListener(listener); + } + + + public void removeContextChangeListener(ContextChangeListener listener) { + view.removeContextChangeListener(listener); + } + + + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + bar1.setEnabled(enabled); + bar2.setEnabled(enabled); + view.setEnabled(enabled); + updateToolStates(); + } + + + private void run(boolean fork, IRunnableWithProgress runnable) { + boolean wasEnabled = isEnabled(); + + try { + // Disable interactions + setEnabled(false); + + // Run segmentation + runnableContext.run(fork, false, runnable); + + } catch (InvocationTargetException ex) { + + // Can't happen without a runtime exception occurring, so re-wrap + throw new RuntimeException(ex); + + } catch (InterruptedException ex) { + + // Can't happen because cancellable is false + throw new RuntimeException(ex); + + } finally { + setEnabled(wasEnabled); + } + } + + + private void segmentWithRunnableContext( + final AnnotationEvent e, + final SegmentationContext ctx) + { + // Fork if the segmenter is slow, and only if our runnable context blocks + boolean fork = blocksOnFork /*&& !segmenter.isFast()*/; + + run(fork, new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) { + monitor.beginTask("Segmenting", IProgressMonitor.UNKNOWN); + try { + segment(e, ctx); + } finally { + monitor.done(); + } + } + }); + } + + + private void start(final SegmentationContext ctx) { + if (ctx != null && hasSegmenter()) { + if (runnableContext == null) { + + // No runnable context + segmenterProxy.init(ctx); + segmenterProxy.update(ctx); + + } else { + + // Run with progress monitor + run(blocksOnFork, new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) { + monitor.beginTask("Initializing", IProgressMonitor.UNKNOWN); + try { + segmenterProxy.init(ctx); + segmenterProxy.update(ctx); + } finally { + monitor.done(); + } + } + }); + + } + + // Repaint everything + repaint(); + } + } + + + private void segment(AnnotationEvent e, SegmentationContext ctx) { + if (hasSegmenter()) { + if (e == null) { + // No event triggered this, so do a full update + segmenterProxy.update(ctx); + + } else { + // Call appropriate segmenter function + switch (e.type) { + case Cleared: + segmenterProxy.update(ctx); + break; + + case Undone: + segmenterProxy.removed(ctx, e.annotation); + break; + + case Redone: + case Added: + segmenterProxy.added(ctx, e.annotation); + break; + + default: + throw new RuntimeException(); + } + } + } + } + + + private boolean isAnnotatingBackground() { + return view.isAnnotatingBackground(); + } + + + private boolean isAnnotatingForeground() { + return view.isAnnotatingForeground(); + } + + + private String getText(Tool a) { + return props.getProperty(getKey(a, "text")); + } + + + private String getToolTip(Tool a) { + return props.getProperty(getKey(a, "tooltip")); + } + + + private ImageDescriptor getImage(Tool a) { + String location = props.getProperty(getKey(a, "image")); + if (location != null) { + if (location.length() == 0) { + return null; + } + + try { + return ImageDescriptor.createFromURL(new URL(location)); + } catch (MalformedURLException e) { + return null; + } + } + + return null; + } + + + private static String getKey(Tool action, String object) { + return String.format("SegmentationView.Action.%s.%s", action, object); + } + + + private int getType(Tool a) { + switch (a) { + case Foreground: + case Background: + case AutoApply: + return Action.AS_CHECK_BOX; + case SetBrushSize: + return Action.AS_DROP_DOWN_MENU; + case SetPainter: + return Action.AS_UNSPECIFIED; + default: + return Action.AS_PUSH_BUTTON; + } + } + + + private void execute(Tool a, Event e) { + switch (a) { + case Foreground: + setAnnotationType(AnnotationType.Foreground); + break; + case Background: + setAnnotationType(AnnotationType.Background); + break; + case ZoomIn: + zoomIn(); + break; + case ZoomOut: + zoomOut(); + break; + case ZoomOriginal: + zoomOriginal(); + break; + case ZoomBestFit: + zoomBestFit(); + break; + case Repaint: + repaint(); + break; + case Undo: + undo(); + break; + case Redo: + redo(); + break; + case Clear: + clear(); + break; + case SetBrushSize: + showBrushControl(e); + break; + case AutoApply: + setAutoApply(a.action.isChecked()); + break; + case Apply: + apply(); + break; + case SetPainter: + setPainter(); + break; + case AssignButton: + assignLabel(); + break; + case SegmenterOptions: + showSegmenterOptions(); + break; + } + + updateToolStates(); + } + + + private void updateToolStates() { + if (isEnabled()) { + Tool.Apply.action.setEnabled(!Tool.AutoApply.action.isChecked()); + Tool.Undo.action.setEnabled(canUndo()); + Tool.Redo.action.setEnabled(canRedo()); + Tool.ZoomIn.action.setEnabled(canZoomIn()); + Tool.ZoomOut.action.setEnabled(canZoomOut()); + Tool.ZoomOriginal.action.setEnabled(canZoomOriginal()); + Tool.ZoomBestFit.action.setEnabled(canZoomBestFit()); + comboLabel.setEnabled(canZoomBestFit()); + assign.setEnabled(canZoomBestFit() & !(comboLabel.getText().isEmpty())); + Tool.Foreground.action.setChecked(isAnnotatingForeground()); + Tool.Background.action.setChecked(isAnnotatingBackground()); + Tool.Clear.action.setEnabled(canClear()); + Tool.AutoApply.action.setChecked(auto); + Tool.SegmenterOptions.action.setEnabled(canShowOptions()); + + // Always enabled if view enabled + Tool.SetBrushSize.action.setEnabled(true); + Tool.SegmenterOptions.action.setEnabled(true); + Tool.SetPainter.action.setEnabled(true); + Tool.Repaint.action.setEnabled(true); + Tool.Foreground.action.setEnabled(true); + Tool.Background.action.setEnabled(true); + Tool.AutoApply.action.setEnabled(true); + + } else { + // Everything disabled + for (Tool t : Tool.values()) { + t.action.setEnabled(false); + } + } + + } + + private void setPainter() { + SegmentationPainter painter = painters.get(combo.getText()); + setPainter(painter); + } + /* + Assign the label to the segment on clicking assign button and update the image segment. + */ + private void assignLabel() { + SegmentationPainter painter = painters.get("Display Label"); + setPainter(painter); + } + + private void setLabel(String content) { + try + { + String content1 = URLEncoder.encode(content.toString(),"UTF-8"); + URL url = new URL("http://palea.cgrb.oregonstate.edu/services/PO_web_service.php?request_type=term_search&search_value="+content1+"&inc_synonyms&branch_filter=plant_anatomy&max=20"); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); + if(connection.getResponseCode() == 200) + { + String inputLine; + JSONObject object = null; + while ((inputLine = in.readLine()) != null) + { + object = new JSONObject(inputLine); + } + JSONArray array = new JSONArray(object.getString("PO_term_search_response")); + String listElement; + for(int i=0; i listeners; + private final ImageControl view; + private SegmentationContext ctx; + private AnnotationTool tool; + private SegmentationPainter painter; + private Cursor cursor; + + public AnnotatedImageControl(Composite parent, int style) { + super(parent, style); + setLayout(new FillLayout()); + view = new ImageControl(this, SWT.NONE); + listeners = new ArrayList(2); + painter = new CombinedPainter(); + view.getCanvas().addMouseMoveListener(cursorChanger); + addDisposeListener(disposeListener); + } + + + public ImageControl getImageControl() { + return view; + } + + + public Canvas getCanvas() { + return view.getCanvas(); + } + + + public SegmentationPainter getPainter() { + return painter; + } + + + public void setPainter(SegmentationPainter painter) { + if (this.painter != painter) { + this.painter = painter; + recreate(); + } + } + + + public SegmentationContext getContext() { + return ctx; + } + + + public void setContext(SegmentationContext ctx) { + + // Remember old context for event + SegmentationContext old = this.ctx; + + // Detach old tool + int lineWidth = 1; + if (tool != null) { + lineWidth = tool.getLineWidth(); + tool.detach(); + tool = null; + } + + // Detach old annotation listener + if (ctx != null) { + ctx.getAnnotations().removeAnnotationListener(listener); + } + + // Assign context + this.ctx = ctx; + + if (ctx != null) { + // Attach new annotation listener + AnnotationManager annotations = ctx.getAnnotations(); + annotations.addAnnotationListener(listener); + + // Attach a new annotation tool + tool = new AnnotationTool(annotations, view); + tool.setLineWidth(lineWidth); + } + + // Create the initial image + recreate(); + + // Fire event + fireContextChanged(old); + } + + + public int getLineWidth() { + if (tool != null) { + return tool.getLineWidth(); + } + return 1; + } + + + public void setLineWidth(int width) { + if (tool != null) { + tool.setLineWidth(width); + } + } + + + public AnnotationType getAnnotationType() { + if (tool != null) { + return tool.getType(); + } + return AnnotationType.Foreground; + } + + + public void setAnnotationType(AnnotationType type) { + if (tool != null) { + tool.setType(type); + } + } + + + public float getZoom() { + return view.getZoom(); + } + + + public void setZoom(float zoom) { + view.setZoom(zoom); + } + + + public float getZoomStep() { + return view.getZoomStep(); + } + + + public void setZoomStep(float zoomStep) { + view.setZoomStep(zoomStep); + } + + + public void zoomBestFit() { + view.zoomBestFit(); + } + + + public void zoomIn() { + view.zoomIn(); + } + + + public void zoomOriginal() { + view.zoomOriginal(); + } + + + public void zoomOut() { + view.zoomOut(); + } + + + public void undo() { + if (ctx != null) { + ctx.getAnnotations().undo(); + } + } + + + public void redo() { + if (ctx != null) { + ctx.getAnnotations().redo(); + } + } + + + public void clear() { + if (ctx != null) { + ctx.getAnnotations().clear(); + } + } + + + public boolean canUndo() { + if (ctx != null) { + return ctx.getAnnotations().canUndo(); + } + return false; + } + + + public boolean canRedo() { + if (ctx != null) { + return ctx.getAnnotations().canRedo(); + } + return false; + } + + + public boolean canClear() { + if (ctx != null) { + return ctx.getAnnotations().count() > 0; + } + return false; + } + + + public boolean canZoomBestFit() { + return view.canZoomBestFit(); + } + + + public boolean canZoomIn() { + return view.canZoomIn(); + } + + + public boolean canZoomOriginal() { + return view.canZoomOriginal(); + } + + + public boolean canZoomOut() { + return view.canZoomOut(); + } + + + /** + * Redraw the entire canvas buffer. + */ + public void repaint() { + if (ctx != null) { + painter.paint(ctx, view.getImage()); + } + } + + + public boolean isAnnotatingForeground() { + return getAnnotationType() == AnnotationType.Foreground; + } + + + public boolean isAnnotatingBackground() { + return getAnnotationType() == AnnotationType.Background; + } + + + public void addAnnotationListener(AnnotationListener listener) { + if (ctx == null) { + throw new IllegalStateException(); + } + ctx.getAnnotations().addAnnotationListener(listener); + } + + + public void removeAnnotationListener(AnnotationListener listener) { + if (ctx != null) { + ctx.getAnnotations().removeAnnotationListener(listener); + } + } + + + public void addZoomListener(ZoomListener listener) { + view.addZoomListener(listener); + } + + + public void removeZoomListener(ZoomListener listener) { + view.removeZoomListener(listener); + } + + + public void addContextChangeListener(ContextChangeListener listener) { + listeners.add(listener); + } + + + public void removeContextChangeListener(ContextChangeListener listener) { + listeners.remove(listener); + } + + + private void fireContextChanged(SegmentationContext old) { + ContextChangedEvent e = null; + for (ContextChangeListener l : listeners) { + if (e == null) { + e = new ContextChangedEvent(this, old, ctx); + } + l.contextChanged(e); + } + } + + + /** + * Re-construct the display image buffer, and dispose the old one if + * necessary. If the context is null, then set the display + * buffer to null and dispose of the old one. + */ + private void recreate() { + if (ctx == null) { + + // Set null image (disposing the old one) + view.setImage(null, true); + + } else { + + // Check if we can reuse what we have + boolean sameSize = false; + if (view.hasImage()) { + if (view.getImageBounds().equals(ctx.getBounds())) { + + // Okay, we can reuse the buffer we have :-) + sameSize = true; + } + } + + if (!sameSize) { + + // Create initial image + ObservableImage buffer = new ObservableImage( + SwtUtils.createImage(ctx.getBounds()) + ); + + // Set the image (disposing the old one) + view.setImage(buffer, true); + } + + // Draw the image + repaint(); + } + } + + + private final DisposeListener disposeListener = new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + if (cursor != null) { + cursor.dispose(); + } + } + }; + + + /** + * Changes the cursor to a cross-hair when mouse is over the image. + * + */ + private final MouseMoveListener cursorChanger = new MouseMoveListener() { + + public void mouseMove(MouseEvent e) { + Canvas canvas = view.getCanvas(); + if (view.imageContains(new Point(e.x, e.y))) { + if (cursor == null) { + cursor = CursorFactory.createCrosshairCursor(); + } + canvas.setCursor(cursor); + } else { + canvas.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_ARROW)); + } + } + }; + + + /** + * Listens for annotations and updates the buffer and view accordingly. + */ + private final AnnotationListener listener = new AnnotationListener() { + + public void annotationUndone(AnnotationEvent e) { + // Suspend notifications to prevent repainting the whole thing + view.getImage().setSuspendNotifications(true); + + // Redraw all to buffer + repaint(); + + // Re-enable notifications + view.getImage().setSuspendNotifications(false); + + // Repaint just the changed area + view.getImage().fireImageChanged(e.annotation.getBounds()); + } + + + public void annotationsCleared(AnnotationEvent e) { + // Repaint everything + repaint(); + } + + + public void annotationRedone(AnnotationEvent e) { + // Paint the new annotation + e.annotation.paint(view.getImage()); + } + + + public void annotationPerformed(AnnotationEvent e) { + // Paint the new annotation + e.annotation.paint(view.getImage()); + } + }; +} diff --git a/Annotation/src/ie/dcu/apps/ist/widgets/BrushControl.java b/Annotation/src/ie/dcu/apps/ist/widgets/BrushControl.java new file mode 100644 index 0000000..9459f79 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/widgets/BrushControl.java @@ -0,0 +1,101 @@ +package ie.dcu.apps.ist.widgets; + +import ie.dcu.swt.PopupComposite; + +import org.eclipse.swt.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +/** + * Pop up control for changing brush sizes. + * + * @author Kevin McGuinness + */ +public class BrushControl extends PopupComposite { + private static final int MAX_BRUSH_SIZE = 20; + + private final Label label; + private final Scale scale; + + + public BrushControl(Shell parent, int style) { + super(parent, style); + + // Create controls + label = new Label(this, SWT.NONE); + scale = new Scale(this, SWT.NONE); + + configureControls(); + configureListeners(); + layoutControls(); + } + + + public void setBrushSize(int size) { + scale.setSelection(size); + updateLabel(); + } + + + public int getBrushSize() { + return scale.getSelection(); + } + + + public void addSelectionListener(SelectionListener listener) { + scale.addSelectionListener(listener); + } + + + public void removeSelectionListener(SelectionListener listener) { + scale.removeSelectionListener(listener); + } + + + private void configureControls() { + scale.setMinimum(1); + scale.setMaximum(MAX_BRUSH_SIZE); + scale.setIncrement(1); + scale.setPageIncrement(2); + setBrushSize(1); + } + + + private void configureListeners() { + scale.addSelectionListener(new ScaleChangeListener()); + } + + + private void layoutControls() { + setLayout(new GridLayout()); + + // Layout label + GridData gd = new GridData(); + gd.grabExcessHorizontalSpace = true; + gd.horizontalAlignment = SWT.FILL; + label.setLayoutData(gd); + + // Layout scale control + gd = new GridData(); + gd.grabExcessHorizontalSpace = true; + gd.horizontalAlignment = SWT.FILL; + gd.minimumWidth = 150; + scale.setLayoutData(gd); + } + + + private void updateLabel() { + int size = scale.getSelection(); + label.setText(String.format("Brush Size: %dpx ", size)); + } + + + private final class ScaleChangeListener + extends SelectionAdapter { + + public void widgetSelected(SelectionEvent e) { + updateLabel(); + } + }; +} diff --git a/Annotation/src/ie/dcu/apps/ist/widgets/ColorSelector.java b/Annotation/src/ie/dcu/apps/ist/widgets/ColorSelector.java new file mode 100644 index 0000000..7efcf9d --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/widgets/ColorSelector.java @@ -0,0 +1,175 @@ +package ie.dcu.apps.ist.widgets; + +import java.beans.*; + +import org.eclipse.jface.resource.*; +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * Button for selecting colors. + * + * @author Kevin McGuinness + */ +public class ColorSelector { + public static final String DATA_KEY = "ColorEditor"; + public static final String COLOR_PROPERTY = "color"; + + private final PropertyChangeSupport pcs; + private final Point extent; + private final Button button; + private final ControlListener listener; + + private Image image; + private RGB rgb; + + + public ColorSelector(Composite parent) { + + pcs = new PropertyChangeSupport(this); + button = new Button(parent, SWT.PUSH); + extent = computeImageSize(parent); + image = new Image(parent.getDisplay(), extent.x, extent.y); + listener = new ControlListener(); + + GC gc = new GC(image); + gc.setBackground(button.getBackground()); + gc.fillRectangle(0, 0, extent.x, extent.y); + gc.dispose(); + + + button.setData(DATA_KEY, this); + button.setImage(image); + button.addListener(SWT.Selection, listener); + button.addListener(SWT.Dispose, listener); + } + + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + + public void addPropertyChangeListener(String name, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(name, listener); + } + + + public PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + + public PropertyChangeListener[] getPropertyChangeListeners(String name) { + return pcs.getPropertyChangeListeners(name); + } + + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + + public void removePropertyChangeListener(String name, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(name, listener); + } + + + public RGB getColor() { + return rgb; + } + + + public void setColor(RGB rgb) { + if (rgb != null && this.rgb != rgb) { + RGB old = rgb; + this.rgb = rgb; + updateImage(); + pcs.firePropertyChange(COLOR_PROPERTY, old, rgb); + } + } + + + public Button getButton() { + return button; + } + + + public void addListener(int eventType, Listener listener) { + button.addListener(eventType, listener); + } + + + public void setLayoutData(Object layoutData) { + button.setLayoutData(layoutData); + } + + + public void setData(Object data) { + button.setData(data); + } + + + public Object getData() { + return button.getData(); + } + + + protected void updateImage() { + Display display = button.getDisplay(); + + GC gc = new GC(image); + gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK)); + gc.drawRectangle(0, 2, extent.x - 1, extent.y - 4); + + Color color = new Color(display, rgb); + gc.setBackground(color); + gc.fillRectangle(1, 3, extent.x - 2, extent.y - 5); + gc.dispose(); + + button.setImage(image); + color.dispose(); + } + + + protected Point computeImageSize(Composite parent) { + GC gc = new GC(parent); + Font f = JFaceResources.getFontRegistry().get(JFaceResources.DEFAULT_FONT); + gc.setFont(f); + int height = gc.getFontMetrics().getHeight(); + gc.dispose(); + Point p = new Point(height * 3 - 6, height); + return p; + } + + + private void handleDispose(Event e) { + if (image != null) { + image.dispose(); + image = null; + } + } + + + private void handleSelection(Event e) { + ColorDialog dialog = new ColorDialog(button.getShell()); + dialog.setRGB(rgb); + RGB rgb = dialog.open(); + setColor(rgb); + } + + + private final class ControlListener implements Listener { + public void handleEvent(Event e) { + switch (e.type) { + case SWT.Selection: + handleSelection(e); + break; + case SWT.Dispose: + handleDispose(e); + break; + } + } + } +} \ No newline at end of file diff --git a/Annotation/src/ie/dcu/apps/ist/widgets/ImageMenuManager.java b/Annotation/src/ie/dcu/apps/ist/widgets/ImageMenuManager.java new file mode 100644 index 0000000..cfe0050 --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/widgets/ImageMenuManager.java @@ -0,0 +1,54 @@ +package ie.dcu.apps.ist.widgets; + +import java.net.URL; + +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; + +public class ImageMenuManager extends MenuManager { + private Image image; + + public ImageMenuManager() { + super(); + } + + public ImageMenuManager(String text) { + super(text); + } + + public ImageMenuManager(String text, URL imageURL) { + super(text); + setImageURL(imageURL); + } + + public void setImageURL(URL url) { + ImageDescriptor descriptor = ImageDescriptor.createFromURL(url); + this.image = descriptor.createImage(); + } + + @Override + public void dispose() { + super.dispose(); + + if (image != null) { + image.dispose(); + } + } + + @Override + public void fill(Menu parent, int index) { + super.fill(parent, index); + MenuItem item = getMenuItem(); + if (item != null) { + item.setImage(image); + } + } + + protected MenuItem getMenuItem() { + Menu menu = getMenu(); + return (menu != null) ? menu.getParentItem() : null; + } +} diff --git a/Annotation/src/ie/dcu/apps/ist/widgets/SwtTimer.java b/Annotation/src/ie/dcu/apps/ist/widgets/SwtTimer.java new file mode 100644 index 0000000..6d1f97c --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/widgets/SwtTimer.java @@ -0,0 +1,642 @@ +package ie.dcu.apps.ist.widgets; + + +import ie.dcu.apps.ist.event.*; + +import java.util.ArrayList; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.*; + +/** + * A timer user interface element. Displays a component used + * to implement a count-down. + * + * @author Kevin McGuinness + */ +public class SwtTimer implements TickerListener { + + /** + * Timer is modeled as a state machine. These are the states. + */ + public static enum State { Initial, Ready, Running, Paused }; + + + /** + * List of listeners interested in changes to the object state. + */ + private final ArrayList stateListeners; + + + /** + * List of listeners interested in timeouts. + */ + private final ArrayList timeoutListeners; + + + /** + * The drawing canvas where the numbers are drawn. + */ + private final Canvas canvas; + + + /** + * The ticker posts tick events every second or so. + */ + private Ticker ticker; + + + /** + * The current state of the timer. + */ + private State state; + + + /** + * The font used to render the numbers. + */ + private Font font; + + + /** + * Total time for the timer, in seconds. + */ + private int time; + + + /** + * Remaining (displayed) time, in seconds. + */ + private int remaining; + + + /** + * Create the timer. Style bits are passed to the underlying canvas. + * + * @param parent + * Parent container. + * @param style + * Style bits. + */ + public SwtTimer(Composite parent, int style) { + stateListeners = new ArrayList(1); + timeoutListeners = new ArrayList(1); + canvas = new Canvas(parent, style); + addListeners(); + enter(State.Initial); + } + + + /** + * Add listeners to various components. + */ + private void addListeners() { + // Listen for paint events + canvas.addPaintListener(new PaintListener() { + public void paintControl(PaintEvent e) { + paint(e.gc); + } + }); + + // Listen for dispose event + canvas.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + dispose(); + } + }); + } + + + /** + * Set the layout data for the component. + * + * @param data + * The layout data. + */ + public void setLayoutData(Object data) { + canvas.setLayoutData(data); + } + + + /** + * Returns the layout data for the component. + * + * @return The layout data. + */ + public Object getLayoutData() { + return canvas.getLayoutData(); + } + + + /** + * Get the contained canvas. + * + * @return The contained canvas. + */ + public Canvas getCanvas() { + return canvas; + } + + + /** + * Returns the shell associated with the canvas. + * + * @return The shell. + */ + public Shell getShell() { + return canvas.getShell(); + } + + + /** + * Get the state of the timer. + * + * @return The timer state. + */ + public State getState() { + return state; + } + + + /** + * Add a state change listener. + * + * @param listener + * The listener. + */ + public void addStateListener(StateListener listener) { + stateListeners.add(listener); + } + + + /** + * Remove a state change listener. + * + * @param listener + * The listener. + */ + public void removeStateListener(StateListener listener) { + stateListeners.remove(listener); + } + + + /** + * Add a time-out listener. + * + * @param listener + * The listener. + */ + public void addTimeoutListener(TimeoutListener listener) { + timeoutListeners.add(listener); + } + + + /** + * Remove a time-out listener. + * + * @param listener + * The listener. + */ + public void removeTimeoutListener(TimeoutListener listener) { + timeoutListeners.remove(listener); + } + + + /** + * Returns an estimate of the elapsed time, in seconds. + * + * @return The elapsed time. + */ + public int getElapsed() { + return time - remaining; + } + + + /** + * Set the timeout for the timer, in seconds. + * + * @param seconds + * The number of seconds on the timer. + * @throws IllegalStateException + * If {@link #canSet()} is false. + */ + public void set(int seconds) throws IllegalStateException { + switch (state) { + case Initial: + case Ready: + time = seconds; + remaining = time; + break; + default: + throw new IllegalStateException(); + } + enter(State.Ready); + + repaint(); + } + + + /** + * Returns true if set can be called. Set cannot be called when + * the timer is running or paused. + * + * @return true if set can be called. + */ + public boolean canSet() { + switch (state) { + case Initial: + case Ready: + return true; + } + return false; + } + + + /** + * Start the timer. A new thread will control the timer count-down, so this + * method returns once it has started. + * + * @throws IllegalStateException + * If {@link #canStart()} is false. + */ + public void start() throws IllegalStateException { + switch (state) { + case Ready: + ticker = new Ticker(this, 1000); + ticker.start(); + break; + case Paused: + ticker.resume(); + break; + default: + throw new IllegalStateException(); + } + + enter(State.Running); + + repaint(); + } + + + /** + * Returns true if start can be called. Start cannot be called + * when the timer is in it's initial or running state. + * + * @return true if start can be called. + */ + public boolean canStart() { + switch (state) { + case Ready: + case Paused: + return true; + } + return false; + } + + + /** + * Pause the count-down. Temporarily suspends the count-down thread. + * + * @throws IllegalStateException + * If {@link #canPause()} is false. + */ + public void pause() throws IllegalStateException { + switch (state) { + case Running: + ticker.pause(); + break; + case Paused: + break; + default: + throw new IllegalStateException(); + } + + enter(State.Paused); + + repaint(); + } + + + /** + * Returns true if pause can be called. Pause cannot be called + * when the timer is in it's initial or ready state. + * + * @return true if pause can be called. + */ + public boolean canPause() { + switch (state) { + case Running: + case Paused: + return true; + } + return false; + } + + + /** + * Reset the timer. Causes the timer to stop and return to the ready + * state, reseting the time-out to the last one set. + * + * @throws IllegalStateException + * If {@link #canReset()} is false. + */ + public void reset() throws IllegalStateException { + switch (state) { + case Ready: + break; + case Running: + case Paused: + ticker.stop(); + ticker = null; + remaining = time; + break; + default: + throw new IllegalStateException(); + } + + enter(State.Ready); + + repaint(); + } + + + /** + * Returns true if reset can be called. Reset cannot be called + * when the timer is in it's initial state. + * + * @return true if reset can be called. + */ + public boolean canReset() { + switch (state) { + case Ready: + case Running: + case Paused: + return true; + } + return false; + } + + + /** + * Clear the timer. Returns the timer to its initial state, stopping + * it if necessary. + */ + public void clear() { + switch (state) { + case Initial: + break; + case Ready: + time = 0; + remaining = 0; + break; + case Running: + case Paused: + ticker.stop(); + ticker = null; + remaining = 0; + time = 0; + break; + } + + enter(State.Initial); + + repaint(); + } + + + /** + * Returns true if clear can be called. + * + * @return Always returns true. + */ + public boolean canClear() { + return true; + } + + + /** + * Tell the timer to repaint itself. + */ + public void repaint() { + if (!canvas.isDisposed()) { + canvas.redraw(); + } + } + + + /** + * Called at each ticker tick interval. Should not be invoked by clients. + */ + public void tick(final TickerEvent evt) { + if (canvas.isDisposed()) { + // Widget is disposed, ignore timer events + return; + } + + long elapsed = evt.getElapsed(); + int remaining = time - (int) (elapsed / 1000); + + if (remaining <= 0) { + // We're done + this.remaining = 0; + + // Stop and nullify ticker + if (ticker != null) { + ticker.stopLater(); + ticker = null; + } + + // Enqueue the ui update the event dispatch thread + canvas.getDisplay().asyncExec(new Runnable() { + public void run() { + enter(State.Initial); + + // repaint + repaint(); + + // fire timeout event + fireTimeoutEvent(); + } + }); + + } else if (this.remaining != remaining) { + + // Update remaining + this.remaining = remaining; + + // Enqueue a repaint + canvas.getDisplay().asyncExec(new Runnable() { + public void run() { + // repaint + repaint(); + } + }); + } + } + + + /** + * Enter the given state. + * + * @param state The state. + */ + private void enter(State state) { + if (this.state != state) { + this.state = state; + fireStateChanged(); + } + } + + + /** + * Fires a state changed event. + */ + private void fireStateChanged() { + if (!stateListeners.isEmpty()) { + StateEvent evt = new StateEvent(this); + for (StateListener s : stateListeners) { + s.stateChanged(evt); + } + } + } + + + /** + * Sends a timeout event to listeners. + */ + private void fireTimeoutEvent() { + if (!timeoutListeners.isEmpty()) { + TimeoutEvent evt = new TimeoutEvent(this); + for (TimeoutListener t : timeoutListeners) { + t.timeoutOccured(evt); + } + } + } + + + /** + * Paints the timer. + * + * @param gc + * The graphics context. + */ + private void paint(GC gc) { + gc.setFont(getTimerFont()); + + int ss = remaining % 60; + int mm = (remaining % 3600) / 60; + int hh = remaining / 3600; + + String timestr = formatTime(ss, mm, hh); + + Point t = getStringDimensions(gc, timestr); + Point c = getCanvasDimension(); + + int x = c.x / 2 - t.x / 2; + int y = c.y / 2 - t.y / 2; + + if (remaining < 20 && state != State.Initial) { + gc.setForeground(getWarningColor()); + } else { + gc.setForeground(getTimerColor()); + } + + gc.drawString(timestr, x, y); + } + + + /** + * Tidies native resources. Called automatically. + */ + private void dispose() { + if (font != null) { + font.dispose(); + font = null; + } + } + + + /** + * Formats a time string. + */ + private String formatTime(int ss, int mm, int hh) { + String timestr; + if (hh == 0) { + timestr = String.format("%02d:%02d", mm, ss); + } else { + timestr = String.format("%02d:%02d:%02d", hh, mm, ss); + } + return timestr; + } + + + /** + * Returns the dimensions of a given string as drawn with the current font on + * the given graphics context. + */ + private static Point getStringDimensions(GC gc, String str) { + int x = 0; + for (int i = 0; i < str.length(); i++) { + x += gc.getAdvanceWidth(str.charAt(i)); + } + int y = gc.getFontMetrics().getHeight(); + return new Point(x,y); + } + + + /** + * Returns the dimensions of the canvas as a point. + * + * @return A point where x is the width and y is the height. + */ + private Point getCanvasDimension() { + Rectangle bounds = canvas.getBounds(); + return new Point(bounds.width, bounds.height); + } + + + private Color getWarningColor() { + return getSystemColor(SWT.COLOR_RED); + } + + + private Color getTimerColor() { + return getSystemColor(SWT.COLOR_DARK_BLUE); + } + + + private Font getTimerFont() { + if (font == null) { + font = new Font(canvas.getDisplay(), "Sans", 30, SWT.NONE); + } + return font; + } + + + private Color getSystemColor(int id) { + return canvas.getDisplay().getSystemColor(id); + } + + public static void main(String[] args) { + Display display = new Display(); + Shell shell = new Shell(display, SWT.SHELL_TRIM); + shell.setBounds(800, 100, 220, 200); + shell.setLayout(new FillLayout()); + + SwtTimer timer = new SwtTimer(shell, SWT.NONE); + timer.set(120); + timer.start(); + + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + display.dispose(); + } + +} diff --git a/Annotation/src/ie/dcu/apps/ist/widgets/Ticker.java b/Annotation/src/ie/dcu/apps/ist/widgets/Ticker.java new file mode 100644 index 0000000..c2d48ab --- /dev/null +++ b/Annotation/src/ie/dcu/apps/ist/widgets/Ticker.java @@ -0,0 +1,246 @@ +package ie.dcu.apps.ist.widgets; + +import ie.dcu.apps.ist.event.*; + + +public class Ticker implements Runnable { + private final TickerListener listener; + + private Thread thread = null; + private boolean pause = false; + private boolean stop = false; + private long napTime = 100; + private long interval = 1000; + private long elapsed = 0; + private long startTime = 0; + private long pausedTime = 0; + + // State variables + private boolean paused = false; + private boolean stopped = true; + + public Ticker(TickerListener listener) { + + // Check listener + if (listener == null) { + throw new IllegalArgumentException(); + } + + this.listener = listener; + } + + + public Ticker(TickerListener listener, long interval) { + + // Check listener + if (listener == null) { + throw new IllegalArgumentException(); + } + + // Check interval + if (interval < 0) { + throw new IllegalArgumentException(); + } + + // Assign + this.listener = listener; + this.interval = interval; + this.napTime = interval / 10; + } + + + public synchronized long elapsed() { + return elapsed; + } + + + public void start() { + if (thread != null) { + throw new IllegalStateException("Cannot restart threads"); + } + thread = new Thread(this, "TimerThread"); + thread.start(); + } + + + public void run() { + + synchronized (this) { + stopped = false; + } + + // Set start time + startTime = System.currentTimeMillis(); + + // Loop + while (true) { + + // Yawn! Z Z z z z Z Z Z z z z Z Z Z ... + sleep(napTime); + + // Wait while thread is paused + synchronized (this) { + if (pause) { + + // Remember when pausing started + long now = System.currentTimeMillis(); + + // Set paused flag to true and notify + paused = true; + notifyAll(); + + // Wait until woken up + while (paused) doWait(); + + // Add duration we've been paused for + pausedTime += System.currentTimeMillis() - now; + + // Clear pause flag && notify + pause = false; + notifyAll(); + } + } + + // Check for stop flag + synchronized (this) { + if (stop) { + stopped = true; + notifyAll(); + break; + } + } + + // HI-HO-HI-HO ... + + work(); + } + } + + + private void work() { + boolean event = false; + + synchronized (this) { + // Calculate total elapsed time in milliseconds + long now = System.currentTimeMillis(); + long elapsed = now - (startTime + pausedTime); + + // Calculate time elapsed since last event + long sinceLast = elapsed - this.elapsed; + if (interval <= sinceLast) { + + // Compensate for any difference + long diff = sinceLast - interval; + + // Its time for another event + this.elapsed = elapsed - diff; + + // Fire event flag + event = true; + } + } + + // Do event + if (event) { + synchronized (listener) { + listener.tick(new TickerEvent(this, elapsed)); + } + } + } + + + public void pause() { + // Pause running thread + synchronized (this) { + pause = true; + + // Wait for pause to occur + while (!paused) doWait(); + } + } + + + public void resume() { + // Wake up paused threads + synchronized (this) { + if (paused) { + paused = false; + notifyAll(); + } + + while (pause) doWait(); + } + } + + + public boolean isPaused() { + synchronized (this) { + return paused; + } + } + + + public void stop() { + + synchronized (this) { + + // Resume paused threads + if (paused) { + paused = false; + notifyAll(); + } + + while (pause) doWait(); + + // Stop + stop = true; + + // Wait until stop block reached + while (!stopped) doWait(); + } + } + + + public void stopLater() { + synchronized (this) { + + // Resume paused threads + if (paused) { + paused = false; + notifyAll(); + } + + while (pause) doWait(); + + // Stop + stop = true; + } + } + + + public boolean isStopped() { + synchronized (this) { + return stopped; + } + } + + + private void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + // Ignore + } + } + + + private void doWait() { + try { + wait(); + } catch (InterruptedException e) { + // ignore + } + } +} + + diff --git a/Annotation/src/ie/dcu/array/Arrays.class b/Annotation/src/ie/dcu/array/Arrays.class new file mode 100644 index 0000000..767b525 Binary files /dev/null and b/Annotation/src/ie/dcu/array/Arrays.class differ diff --git a/Annotation/src/ie/dcu/array/Arrays.java b/Annotation/src/ie/dcu/array/Arrays.java new file mode 100644 index 0000000..755c087 --- /dev/null +++ b/Annotation/src/ie/dcu/array/Arrays.java @@ -0,0 +1,3233 @@ +package ie.dcu.array; + +import java.lang.reflect.Array; + +/** + * Collection of static methods on arrays. + * + * @author Kevin McGuinness + */ +public class Arrays { + + /** + * Clamp the values in the given byte matrix to the given range. + * + * The values array is modified (if necessary). + * + * The passed array must be one of the following types: + *
    + *
  • byte[]
  • + *
  • short[]
  • + *
  • int[]
  • + *
  • long[]
  • + *
  • float[]
  • + *
  • double[]
  • + *
+ * + * @param array + * An array. + * @param min + * The minimum value. + * @param max + * The maximum value. + * @return + * The modified input matrix. + * @throws UnsupportedOperationException + * If the passed array is not one of the supported types. + */ + public static Object clamp(Object array, Number min, Number max) + throws UnsupportedOperationException + { + if (array instanceof byte[]) { + return clamp((byte[]) array, min.byteValue(), max.byteValue()); + } else if (array instanceof short[]) { + return clamp((short[]) array, min.shortValue(), max.shortValue()); + } else if (array instanceof int[]) { + return clamp((int[]) array, min.intValue(), max.intValue()); + } else if (array instanceof long[]) { + return clamp((long[]) array, min.longValue(), max.longValue()); + } else if (array instanceof float[]) { + return clamp((float[]) array, min.longValue(), max.longValue()); + } else if (array instanceof double[]) { + return clamp((double[]) array, min.longValue(), max.longValue()); + } else { + throw new UnsupportedOperationException(); + } + } + + /** + * Clamp the values in the given byte matrix to the given range. + * + * The values array is modified (if necessary). + * + * @param values + * A matrix of byte values. + * @param min + * The minimum value. + * @param max + * The maximum value. + * @return The modified input matrix. + */ + public static byte[] clamp(byte[] values, byte min, byte max) { + if (min > max) { + throw new IllegalArgumentException("min > max"); + } + + for (int i = 0; i < values.length; i++) { + if (values[i] < min) { + values[i] = min; + } + + if (values[i] > max) { + values[i] = max; + } + } + + return values; + } + + /** + * Clamp the values in the given short matrix to the given range. + * + * The values array is modified (if necessary). + * + * @param values + * A matrix of short values. + * @param min + * The minimum value. + * @param max + * The maximum value. + * @return The modified input matrix. + */ + public static short[] clamp(short[] values, short min, short max) { + if (min > max) { + throw new IllegalArgumentException("min > max"); + } + + for (int i = 0; i < values.length; i++) { + if (values[i] < min) { + values[i] = min; + } + + if (values[i] > max) { + values[i] = max; + } + } + + return values; + } + + /** + * Clamp the values in the given int matrix to the given range. + * + * The values array is modified (if necessary). + * + * @param values + * A matrix of int values. + * @param min + * The minimum value. + * @param max + * The maximum value. + * @return The modified input matrix. + */ + public static int[] clamp(int[] values, int min, int max) { + if (min > max) { + throw new IllegalArgumentException("min > max"); + } + + for (int i = 0; i < values.length; i++) { + if (values[i] < min) { + values[i] = min; + } + + if (values[i] > max) { + values[i] = max; + } + } + + return values; + } + + /** + * Clamp the values in the given long matrix to the given range. + * + * The values array is modified (if necessary). + * + * @param values + * A matrix of long values. + * @param min + * The minimum value. + * @param max + * The maximum value. + * @return The modified input matrix. + */ + public static long[] clamp(long[] values, long min, long max) { + if (min > max) { + throw new IllegalArgumentException("min > max"); + } + + for (int i = 0; i < values.length; i++) { + if (values[i] < min) { + values[i] = min; + } + + if (values[i] > max) { + values[i] = max; + } + } + + return values; + } + + /** + * Clamp the values in the given float matrix to the given range. + * + * The values array is modified (if necessary). + * + * @param values + * A matrix of float values. + * @param min + * The minimum value. + * @param max + * The maximum value. + * @return The modified input matrix. + */ + public static float[] clamp(float[] values, float min, float max) { + if (min > max) { + throw new IllegalArgumentException("min > max"); + } + + for (int i = 0; i < values.length; i++) { + if (values[i] < min) { + values[i] = min; + } + + if (values[i] > max) { + values[i] = max; + } + } + + return values; + } + + /** + * Clamp the values in the given double matrix to the given range. + * + * The values array is modified (if necessary). + * + * @param values + * A matrix of double values. + * @param min + * The minimum value. + * @param max + * The maximum value. + * @return The modified input matrix. + */ + public static double[] clamp(double[] values, double min, double max) { + if (min > max) { + throw new IllegalArgumentException("min > max"); + } + + for (int i = 0; i < values.length; i++) { + if (values[i] < min) { + values[i] = min; + } + + if (values[i] > max) { + values[i] = max; + } + } + + return values; + } + + /** + * Filter the values in the given array. + * + * @param array + * An array. + * @param filter + * A filter. + * @return + * The filtered array. + */ + @SuppressWarnings("unchecked") + public static T[] filter(T[] array, Filter filter) { + T[] buffer = (T[]) Array.newInstance( + array.getClass().getComponentType(), array.length); + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + + /** + * Filter the values in the given byte array. + * + * This method is potentially more efficient than the generic Filter + * version, since it must box each value in the array. + * + * @param array + * An array of bytes. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static byte[] filter(byte[] array, Filter.Byte filter) { + byte[] buffer = new byte[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Filter the values in the given byte array. + * + * @param array + * An array of bytes. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static byte[] filter(byte[] array, Filter filter) { + byte[] buffer = new byte[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Filter the values in the given short array. + * + * This method is potentially more efficient than the generic Filter + * version, since it must box each value in the array. + * + * @param array + * An array of shorts. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static short[] filter(short[] array, Filter.Short filter) { + short[] buffer = new short[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Filter the values in the given short array. + * + * @param array + * An array of shorts. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static short[] filter(short[] array, Filter filter) { + short[] buffer = new short[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Filter the values in the given int array. + * + * This method is potentially more efficient than the generic Filter + * version, since it must box each value in the array. + * + * @param array + * An array of ints. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static int[] filter(int[] array, Filter.Integer filter) { + int[] buffer = new int[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Filter the values in the given int array. + * + * @param array + * An array of ints. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static int[] filter(int[] array, Filter filter) { + int[] buffer = new int[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Filter the values in the given long array. + * + * This method is potentially more efficient than the generic Filter + * version, since it must box each value in the array. + * + * @param array + * An array of longs. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static long[] filter(long[] array, Filter.Long filter) { + long[] buffer = new long[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Filter the values in the given long array. + * + * @param array + * An array of longs. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static long[] filter(long[] array, Filter filter) { + long[] buffer = new long[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Filter the values in the given float array. + * + * This method is potentially more efficient than the generic Filter + * version, since it must box each value in the array. + * + * @param array + * An array of floats. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static float[] filter(float[] array, Filter.Float filter) { + float[] buffer = new float[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Filter the values in the given float array. + * + * @param array + * An array of floats. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static float[] filter(float[] array, Filter filter) { + float[] buffer = new float[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Filter the values in the given double array. + * + * This method is potentially more efficient than the generic Filter + * version, since it must box each value in the array. + * + * @param array + * An array of doubles. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static double[] filter(double[] array, Filter.Double filter) { + double[] buffer = new double[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Filter the values in the given double array. + * + * @param array + * An array of doubles. + * @param filter + * A filter. + * @return + * The filtered array. + */ + public static double[] filter(double[] array, Filter filter) { + double[] buffer = new double[array.length]; + + int count = 0; + for (int i = 0; i < array.length; i++) { + if (filter.retain(array[i])) { + buffer[count++] = array[i]; + } + } + + return subarray(buffer, 0, count); + } + + /** + * Returns a sub-array of the given array. + * + * @param array + * The array of bytes. + * @param startPos + * The start position. + * @param count + * The number of elements. + * @return + * The sub-array. + * @throws IndexOutOfBoundsException + * If the operation would result in an index out of bounds + * error. + */ + @SuppressWarnings("unchecked") + public static T[] subarray(T[] array, int startPos, int count) { + checkSubarray(array.length, startPos, count); + T[] result = (T[]) Array.newInstance( + array.getClass().getComponentType(), count); + System.arraycopy(array, 0, result, 0, count); + return result; + } + + /** + * Returns a sub-array of the given array. + * + * @param array + * The array of bytes. + * @param startPos + * The start position. + * @param count + * The number of elements. + * @return + * The sub-array. + * @throws IndexOutOfBoundsException + * If the operation would result in an index out of bounds + * error. + */ + public static byte[] subarray(byte[] array, int startPos, int count) { + checkSubarray(array.length, startPos, count); + byte[] result = new byte[count]; + System.arraycopy(array, 0, result, 0, count); + return result; + } + + /** + * Returns a sub-array of the given array. + * + * @param array + * The array of shorts. + * @param startPos + * The start position. + * @param count + * The number of elements. + * @return + * The sub-array. + * @throws IndexOutOfBoundsException + * If the operation would result in an index out of bounds + * error. + */ + public static short[] subarray(short[] array, int startPos, int count) { + checkSubarray(array.length, startPos, count); + short[] result = new short[count]; + System.arraycopy(array, 0, result, 0, count); + return result; + } + + /** + * Returns a sub-array of the given array. + * + * @param array + * The array of ints. + * @param startPos + * The start position. + * @param count + * The number of elements. + * @return + * The sub-array. + * @throws IndexOutOfBoundsException + * If the operation would result in an index out of bounds + * error. + */ + public static int[] subarray(int[] array, int startPos, int count) { + checkSubarray(array.length, startPos, count); + int[] result = new int[count]; + System.arraycopy(array, 0, result, 0, count); + return result; + } + + /** + * Returns a sub-array of the given array. + * + * @param array + * The array of longs. + * @param startPos + * The start position. + * @param count + * The number of elements. + * @return + * The sub-array. + * @throws IndexOutOfBoundsException + * If the operation would result in an index out of bounds + * error. + */ + public static long[] subarray(long[] array, int startPos, int count) { + checkSubarray(array.length, startPos, count); + long[] result = new long[count]; + System.arraycopy(array, 0, result, 0, count); + return result; + } + + /** + * Returns a sub-array of the given array. + * + * @param array + * The array of floats. + * @param startPos + * The start position. + * @param count + * The number of elements. + * @return + * The sub-array. + * @throws IndexOutOfBoundsException + * If the operation would result in an index out of bounds + * error. + */ + public static float[] subarray(float[] array, int startPos, int count) { + checkSubarray(array.length, startPos, count); + float[] result = new float[count]; + System.arraycopy(array, 0, result, 0, count); + return result; + } + + /** + * Returns a sub-array of the given array. + * + * @param array + * The array of doubles. + * @param startPos + * The start position. + * @param count + * The number of elements. + * @return + * The sub-array. + * @throws IndexOutOfBoundsException + * If the operation would result in an index out of bounds + * error. + */ + public static double[] subarray(double[] array, int startPos, int count) { + checkSubarray(array.length, startPos, count); + double[] result = new double[count]; + System.arraycopy(array, 0, result, 0, count); + return result; + } + + /** + * Check if the subarray operation will result in an + * {@link IndexOutOfBoundsException} + */ + private static void checkSubarray(int length, int startPos, int count) { + if (startPos < 0) { + throw new IndexOutOfBoundsException("startPos < 0"); + } + + if (count < 0) { + throw new IndexOutOfBoundsException("count < 0"); + } + + if (startPos + count > length) { + throw new IndexOutOfBoundsException("startPos + count > array.length"); + } + } + + /** + * Perform a reduction on the given array of bytes. + * + * @param array + * An array. + * @param initialValue + * The initial value for the reduction. + * @param operation + * The reduction operation. + * @return + * The result of the reduction. + */ + public static U reduce(T[] array, U initialValue, + Reduction operation) + { + U accumulator = initialValue; + for (int i = 0; i < array.length; i++) { + accumulator = operation.reduce(accumulator, array[i], i); + } + return accumulator; + } + + /** + * Perform a reduction on the given array of bytes. + * + * @param array + * An array of bytes. + * @param initialValue + * The initial value for the reduction. + * @param operation + * The reduction operation. + * @return + * The result of the reduction. + */ + public static long reduce(byte[] array, long initialValue, + Reduction.Long operation) + { + long accumulator = initialValue; + for (int i = 0; i < array.length; i++) { + accumulator = operation.reduce(accumulator, array[i], i); + } + return accumulator; + } + + /** + * Perform a reduction on the given array of shorts. + * + * @param array + * An array of shorts. + * @param initialValue + * The initial value for the reduction. + * @param operation + * The reduction operation. + * @return + * The result of the reduction. + */ + public static long reduce(short[] array, long initialValue, + Reduction.Long operation) + { + long accumulator = initialValue; + for (int i = 0; i < array.length; i++) { + accumulator = operation.reduce(accumulator, array[i], i); + } + return accumulator; + } + + /** + * Perform a reduction on the given array of ints. + * + * @param array + * An array of ints. + * @param initialValue + * The initial value for the reduction. + * @param operation + * The reduction operation. + * @return + * The result of the reduction. + */ + public static long reduce(int[] array, long initialValue, + Reduction.Long operation) + { + long accumulator = initialValue; + for (int i = 0; i < array.length; i++) { + accumulator = operation.reduce(accumulator, array[i], i); + } + return accumulator; + } + + /** + * Perform a reduction on the given array of longs. + * + * @param array + * An array of longs. + * @param initialValue + * The initial value for the reduction. + * @param operation + * The reduction operation. + * @return + * The result of the reduction. + */ + public static long reduce(long[] array, long initialValue, + Reduction.Long operation) + { + long accumulator = initialValue; + for (int i = 0; i < array.length; i++) { + accumulator = operation.reduce(accumulator, array[i], i); + } + return accumulator; + } + + /** + * Perform a reduction on the given array of floats. + * + * @param array + * An array of floats. + * @param initialValue + * The initial value for the reduction. + * @param operation + * The reduction operation. + * @return + * The result of the reduction. + */ + public static double reduce(float[] array, double initialValue, + Reduction.Double operation) + { + double accumulator = initialValue; + for (int i = 0; i < array.length; i++) { + accumulator = operation.reduce(accumulator, array[i], i); + } + return accumulator; + } + + /** + * Perform a reduction on the given array of doubles. + * + * @param array + * An array of doubles. + * @param initialValue + * The initial value for the reduction. + * @param operation + * The reduction operation. + * @return + * The result of the reduction. + */ + public static double reduce(double[] array, double initialValue, + Reduction.Double operation) + { + double accumulator = initialValue; + for (int i = 0; i < array.length; i++) { + accumulator = operation.reduce(accumulator, array[i], i); + } + return accumulator; + } + + /** + * Finds the sum of all elements in the given array. + * + * The passed array must be one of the following types: + *
    + *
  • byte[]
  • + *
  • short[]
  • + *
  • int[]
  • + *
  • long[]
  • + *
  • float[]
  • + *
  • double[]
  • + *
+ * + * @param array + * An array. + * @return + * The sum of all elements in the given array as a Number. + * @throws UnsupportedOperationException + * If the passed array is not one of the supported types. + */ + public static Number sum(Object array) + throws UnsupportedOperationException + { + if (array instanceof byte[]) { + return sum((byte[]) array); + } else if (array instanceof short[]) { + return sum((short[]) array); + } else if (array instanceof int[]) { + return sum((int[]) array); + } else if (array instanceof long[]) { + return sum((long[]) array); + } else if (array instanceof float[]) { + return sum((float[]) array); + } else if (array instanceof double[]) { + return sum((double[]) array); + } else { + throw new UnsupportedOperationException(); + } + } + + /** + * Computes the sum of all the elements in the given byte array. + * + * @param array + * An array of bytes. + * @return + * The sum of all elements in the array. + */ + public static long sum(byte[] array) { + long sumValue = 0; + for (int i = 0; i < array.length; i++) { + sumValue += array[i]; + } + return sumValue; + } + + /** + * Computes the sum of all the elements in the given short array. + * + * @param array + * An array of shorts. + * @return + * The sum of all elements in the array. + */ + public static long sum(short[] array) { + long sumValue = 0; + for (int i = 0; i < array.length; i++) { + sumValue += array[i]; + } + return sumValue; + } + + /** + * Computes the sum of all the elements in the given int array. + * + * @param array + * An array of ints. + * @return + * The sum of all elements in the array. + */ + public static long sum(int[] array) { + long sumValue = 0; + for (int i = 0; i < array.length; i++) { + sumValue += array[i]; + } + return sumValue; + } + + /** + * Computes the sum of all the elements in the given long array. + * + * @param array + * An array of longs. + * @return + * The sum of all elements in the array. + */ + public static long sum(long[] array) { + long sumValue = 0; + for (int i = 0; i < array.length; i++) { + sumValue += array[i]; + } + return sumValue; + } + + /** + * Computes the sum of all the elements in the given float array. + * + * @param array + * An array of floats. + * @return + * The sum of all elements in the array. + */ + public static double sum(float[] array) { + double sumValue = 0; + for (int i = 0; i < array.length; i++) { + sumValue += array[i]; + } + return sumValue; + } + + /** + * Computes the sum of all the elements in the given double array. + * + * @param array + * An array of doubles. + * @return + * The sum of all elements in the array. + */ + public static double sum(double[] array) { + double sumValue = 0; + for (int i = 0; i < array.length; i++) { + sumValue += array[i]; + } + return sumValue; + } + + /** + * Finds the minimum number in the given array. + * + * The passed array must be one of the following types: + *
    + *
  • byte[]
  • + *
  • short[]
  • + *
  • int[]
  • + *
  • long[]
  • + *
  • float[]
  • + *
  • double[]
  • + *
+ * + * @param array + * An array. + * @return The smallest number, or null if the length of the + * array is zero. + * @throws UnsupportedOperationException + * If the passed array is not one of the supported types. + */ + public static Number min(Object array) + throws UnsupportedOperationException + { + if (array instanceof byte[]) { + return min((byte[]) array); + } else if (array instanceof short[]) { + return min((short[]) array); + } else if (array instanceof int[]) { + return min((int[]) array); + } else if (array instanceof long[]) { + return min((long[]) array); + } else if (array instanceof float[]) { + return min((float[]) array); + } else if (array instanceof double[]) { + return min((double[]) array); + } else { + throw new UnsupportedOperationException(); + } + } + + /** + * Finds the maximum number in the given array. + * + * The passed array must be one of the following types: + *
    + *
  • byte[]
  • + *
  • short[]
  • + *
  • int[]
  • + *
  • long[]
  • + *
  • float[]
  • + *
  • double[]
  • + *
+ * + * @param array + * An array. + * @return The largest number, or null if the length of the + * array is zero. + * @throws UnsupportedOperationException + * If the passed array is not one of the supported types. + */ + public static Number max(Object array) + throws UnsupportedOperationException + { + if (array instanceof byte[]) { + return max((byte[]) array); + } else if (array instanceof short[]) { + return max((short[]) array); + } else if (array instanceof int[]) { + return max((int[]) array); + } else if (array instanceof long[]) { + return max((long[]) array); + } else if (array instanceof float[]) { + return max((float[]) array); + } else if (array instanceof double[]) { + return max((double[]) array); + } else { + throw new UnsupportedOperationException(); + } + } + + /** + * Returns the smallest element in the given byte array. + * + * @param array + * An array of bytes. + * @return The smallest element, or null if the length of the + * array is zero. + */ + public static Byte min(byte[] array) { + if (array.length > 0) { + byte minimum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] < minimum) { + minimum = array[i]; + } + } + return minimum; + } + return null; + } + + /** + * Returns the largest element in the given byte array. + * + * @param array + * An array of bytes. + * @return The largest element, or null if the length of the + * array is zero. + */ + public static Byte max(byte[] array) { + if (array.length > 0) { + byte maximum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > maximum) { + maximum = array[i]; + } + } + return maximum; + } + return null; + } + + /** + * Returns the smallest element in the given short array. + * + * @param array + * An array of shorts. + * @return The smallest element, or null if the length of the + * array is zero. + */ + public static Short min(short[] array) { + if (array.length > 0) { + short minimum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] < minimum) { + minimum = array[i]; + } + } + return minimum; + } + return null; + } + + /** + * Returns the largest element in the given short array. + * + * @param array + * An array of shorts. + * @return The largest element, or null if the length of the + * array is zero. + */ + public static Short max(short[] array) { + if (array.length > 0) { + short maximum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > maximum) { + maximum = array[i]; + } + } + return maximum; + } + return null; + } + + /** + * Returns the smallest element in the given int array. + * + * @param array + * An array of ints. + * @return The smallest element, or null if the length of the + * array is zero. + */ + public static Integer min(int[] array) { + if (array.length > 0) { + int minimum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] < minimum) { + minimum = array[i]; + } + } + return minimum; + } + return null; + } + + /** + * Returns the largest element in the given int array. + * + * @param array + * An array of ints. + * @return The largest element, or null if the length of the + * array is zero. + */ + public static Integer max(int[] array) { + if (array.length > 0) { + int maximum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > maximum) { + maximum = array[i]; + } + } + return maximum; + } + return null; + } + + /** + * Returns the smallest element in the given long array. + * + * @param array + * An array of longs. + * @return The smallest element, or null if the length of the + * array is zero. + */ + public static Long min(long[] array) { + if (array.length > 0) { + long minimum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] < minimum) { + minimum = array[i]; + } + } + return minimum; + } + return null; + } + + /** + * Returns the largest element in the given long array. + * + * @param array + * An array of longs. + * @return The largest element, or null if the length of the + * array is zero. + */ + public static Long max(long[] array) { + if (array.length > 0) { + long maximum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > maximum) { + maximum = array[i]; + } + } + return maximum; + } + return null; + } + + /** + * Returns the smallest element in the given float array. + * + * @param array + * An array of floats. + * @return The smallest element, or null if the length of the + * array is zero. + */ + public static Float min(float[] array) { + if (array.length > 0) { + float minimum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] < minimum) { + minimum = array[i]; + } + } + return minimum; + } + return null; + } + + /** + * Returns the largest element in the given float array. + * + * @param array + * An array of floats. + * @return The largest element, or null if the length of the + * array is zero. + */ + public static Float max(float[] array) { + if (array.length > 0) { + float maximum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > maximum) { + maximum = array[i]; + } + } + return maximum; + } + return null; + } + + /** + * Returns the smallest element in the given double array. + * + * @param array + * An array of doubles. + * @return The smallest element, or null if the length of the + * array is zero. + */ + public static Double min(double[] array) { + if (array.length > 0) { + double minimum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] < minimum) { + minimum = array[i]; + } + } + return minimum; + } + return null; + } + + /** + * Returns the largest element in the given double array. + * + * @param array + * An array of doubles. + * @return The largest element, or null if the length of the + * array is zero. + */ + public static Double max(double[] array) { + if (array.length > 0) { + double maximum = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > maximum) { + maximum = array[i]; + } + } + return maximum; + } + return null; + } + + /** + * Copies an array from the specified source array, beginning at the + * specified position, to the specified position of the destination array. + * + * This method uses {@link System#arraycopy(Object, int, Object, int, int)} + * if the source and destination array are of the same type, otherwise + * it sees if there is a compatible static copy method in this class + * that can perform the conversion copy. If one cannot be found, an + * {@link ArrayStoreException} is thrown. + * + * If the positions or lengths specified are out of range then an + * {@link IndexOutOfBoundsException} is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws ArrayStoreException + * if an element in the source array could not be stored into the + * destination array because of a type mismatch, and there is no + * primitive copy conversion routine to handle the conversion. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(Object src, Object dst) { + copy(src, 0, dst, 0, Array.getLength(dst)); + } + + /** + * Copies an array from the specified source array, beginning at the + * specified position, to the specified position of the destination array. + * + * @see #copy(Object, int, Object, int, int) + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws ArrayStoreException + * if an element in the source array could not be stored into the + * destination array because of a type mismatch, and there is no + * primitive copy conversion routine to handle the conversion. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(Object src, int srcPos, + Object dst, int dstPos, int length) + { + if (dst.getClass().equals(src.getClass())) { + + // Use the fast system copy + System.arraycopy(src, srcPos, dst, dstPos, length); + + } else { + // Try for arrays of different primitive types + + if (src instanceof byte[] && dst instanceof short[]) { + + // Copy from an array of bytes to array of shorts + copy((byte[]) src, srcPos, (short[]) dst, dstPos, length); + + } else if (src instanceof byte[] && dst instanceof int[]) { + + // Copy from an array of bytes to array of ints + copy((byte[]) src, srcPos, (int[]) dst, dstPos, length); + + } else if (src instanceof byte[] && dst instanceof long[]) { + + // Copy from an array of bytes to array of longs + copy((byte[]) src, srcPos, (long[]) dst, dstPos, length); + + } else if (src instanceof byte[] && dst instanceof float[]) { + + // Copy from an array of bytes to array of floats + copy((byte[]) src, srcPos, (float[]) dst, dstPos, length); + + } else if (src instanceof byte[] && dst instanceof double[]) { + + // Copy from an array of bytes to array of doubles + copy((byte[]) src, srcPos, (double[]) dst, dstPos, length); + + } else if (src instanceof short[] && dst instanceof byte[]) { + + // Copy from an array of shorts to array of bytes + copy((short[]) src, srcPos, (byte[]) dst, dstPos, length); + + } else if (src instanceof short[] && dst instanceof int[]) { + + // Copy from an array of shorts to array of ints + copy((short[]) src, srcPos, (int[]) dst, dstPos, length); + + } else if (src instanceof short[] && dst instanceof long[]) { + + // Copy from an array of shorts to array of longs + copy((short[]) src, srcPos, (long[]) dst, dstPos, length); + + } else if (src instanceof short[] && dst instanceof float[]) { + + // Copy from an array of shorts to array of floats + copy((short[]) src, srcPos, (float[]) dst, dstPos, length); + + } else if (src instanceof short[] && dst instanceof double[]) { + + // Copy from an array of shorts to array of doubles + copy((short[]) src, srcPos, (double[]) dst, dstPos, length); + + } else if (src instanceof int[] && dst instanceof byte[]) { + + // Copy from an array of ints to array of bytes + copy((int[]) src, srcPos, (byte[]) dst, dstPos, length); + + } else if (src instanceof int[] && dst instanceof short[]) { + + // Copy from an array of ints to array of shorts + copy((int[]) src, srcPos, (short[]) dst, dstPos, length); + + } else if (src instanceof int[] && dst instanceof long[]) { + + // Copy from an array of ints to array of longs + copy((int[]) src, srcPos, (long[]) dst, dstPos, length); + + } else if (src instanceof int[] && dst instanceof float[]) { + + // Copy from an array of ints to array of floats + copy((int[]) src, srcPos, (float[]) dst, dstPos, length); + + } else if (src instanceof int[] && dst instanceof double[]) { + + // Copy from an array of ints to array of doubles + copy((int[]) src, srcPos, (double[]) dst, dstPos, length); + + } else if (src instanceof long[] && dst instanceof byte[]) { + + // Copy from an array of longs to array of bytes + copy((long[]) src, srcPos, (byte[]) dst, dstPos, length); + + } else if (src instanceof long[] && dst instanceof short[]) { + + // Copy from an array of longs to array of shorts + copy((long[]) src, srcPos, (short[]) dst, dstPos, length); + + } else if (src instanceof long[] && dst instanceof int[]) { + + // Copy from an array of longs to array of ints + copy((long[]) src, srcPos, (int[]) dst, dstPos, length); + + } else if (src instanceof long[] && dst instanceof float[]) { + + // Copy from an array of longs to array of floats + copy((long[]) src, srcPos, (float[]) dst, dstPos, length); + + } else if (src instanceof long[] && dst instanceof double[]) { + + // Copy from an array of longs to array of doubles + copy((long[]) src, srcPos, (double[]) dst, dstPos, length); + + } else if (src instanceof float[] && dst instanceof byte[]) { + + // Copy from an array of floats to array of bytes + copy((float[]) src, srcPos, (byte[]) dst, dstPos, length); + + } else if (src instanceof float[] && dst instanceof short[]) { + + // Copy from an array of floats to array of shorts + copy((float[]) src, srcPos, (short[]) dst, dstPos, length); + + } else if (src instanceof float[] && dst instanceof int[]) { + + // Copy from an array of floats to array of ints + copy((float[]) src, srcPos, (int[]) dst, dstPos, length); + + } else if (src instanceof float[] && dst instanceof long[]) { + + // Copy from an array of floats to array of longs + copy((float[]) src, srcPos, (long[]) dst, dstPos, length); + + } else if (src instanceof float[] && dst instanceof double[]) { + + // Copy from an array of floats to array of doubles + copy((float[]) src, srcPos, (double[]) dst, dstPos, length); + + } else if (src instanceof double[] && dst instanceof byte[]) { + + // Copy from an array of doubles to array of bytes + copy((double[]) src, srcPos, (byte[]) dst, dstPos, length); + + } else if (src instanceof double[] && dst instanceof short[]) { + + // Copy from an array of doubles to array of shorts + copy((double[]) src, srcPos, (short[]) dst, dstPos, length); + + } else if (src instanceof double[] && dst instanceof int[]) { + + // Copy from an array of doubles to array of ints + copy((double[]) src, srcPos, (int[]) dst, dstPos, length); + + } else if (src instanceof double[] && dst instanceof long[]) { + + // Copy from an array of doubles to array of longs + copy((double[]) src, srcPos, (long[]) dst, dstPos, length); + + } else if (src instanceof double[] && dst instanceof float[]) { + + // Copy from an array of doubles to array of floats + copy((double[]) src, srcPos, (float[]) dst, dstPos, length); + + } else { + + throw new ArrayStoreException(); + } + } + } + + /** + * Copy from an array of bytes to array of shorts. + * + * The values will be cast to short. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(byte[] src, int srcPos, + short[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (short) src[srcPos++]; + } + } + + /** + * Copy from an array of bytes to array of shorts. + * + * The values will be cast to short. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(byte[] src, short[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of bytes to array of ints. + * + * The values will be cast to int. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(byte[] src, int srcPos, + int[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (int) src[srcPos++]; + } + } + + /** + * Copy from an array of bytes to array of ints. + * + * The values will be cast to int. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(byte[] src, int[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of bytes to array of longs. + * + * The values will be cast to long. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(byte[] src, int srcPos, + long[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (long) src[srcPos++]; + } + } + + /** + * Copy from an array of bytes to array of longs. + * + * The values will be cast to long. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(byte[] src, long[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of bytes to array of floats. + * + * The values will be cast to float. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(byte[] src, int srcPos, + float[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (float) src[srcPos++]; + } + } + + /** + * Copy from an array of bytes to array of floats. + * + * The values will be cast to float. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(byte[] src, float[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of bytes to array of doubles. + * + * The values will be cast to double. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(byte[] src, int srcPos, + double[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (double) src[srcPos++]; + } + } + + /** + * Copy from an array of bytes to array of doubles. + * + * The values will be cast to double. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(byte[] src, double[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of shorts to array of bytes. + * + * The values will be cast to byte. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(short[] src, int srcPos, + byte[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (byte) src[srcPos++]; + } + } + + /** + * Copy from an array of shorts to array of bytes. + * + * The values will be cast to byte. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(short[] src, byte[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of shorts to array of ints. + * + * The values will be cast to int. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(short[] src, int srcPos, + int[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (int) src[srcPos++]; + } + } + + /** + * Copy from an array of shorts to array of ints. + * + * The values will be cast to int. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(short[] src, int[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of shorts to array of longs. + * + * The values will be cast to long. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(short[] src, int srcPos, + long[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (long) src[srcPos++]; + } + } + + /** + * Copy from an array of shorts to array of longs. + * + * The values will be cast to long. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(short[] src, long[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of shorts to array of floats. + * + * The values will be cast to float. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(short[] src, int srcPos, + float[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (float) src[srcPos++]; + } + } + + /** + * Copy from an array of shorts to array of floats. + * + * The values will be cast to float. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(short[] src, float[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of shorts to array of doubles. + * + * The values will be cast to double. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(short[] src, int srcPos, + double[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (double) src[srcPos++]; + } + } + + /** + * Copy from an array of shorts to array of doubles. + * + * The values will be cast to double. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(short[] src, double[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of ints to array of bytes. + * + * The values will be cast to byte. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(int[] src, int srcPos, + byte[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (byte) src[srcPos++]; + } + } + + /** + * Copy from an array of ints to array of bytes. + * + * The values will be cast to byte. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(int[] src, byte[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of ints to array of shorts. + * + * The values will be cast to short. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(int[] src, int srcPos, + short[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (short) src[srcPos++]; + } + } + + /** + * Copy from an array of ints to array of shorts. + * + * The values will be cast to short. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(int[] src, short[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of ints to array of longs. + * + * The values will be cast to long. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(int[] src, int srcPos, + long[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (long) src[srcPos++]; + } + } + + /** + * Copy from an array of ints to array of longs. + * + * The values will be cast to long. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(int[] src, long[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of ints to array of floats. + * + * The values will be cast to float. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(int[] src, int srcPos, + float[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (float) src[srcPos++]; + } + } + + /** + * Copy from an array of ints to array of floats. + * + * The values will be cast to float. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(int[] src, float[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of ints to array of doubles. + * + * The values will be cast to double. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(int[] src, int srcPos, + double[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (double) src[srcPos++]; + } + } + + /** + * Copy from an array of ints to array of doubles. + * + * The values will be cast to double. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(int[] src, double[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of longs to array of bytes. + * + * The values will be cast to byte. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(long[] src, int srcPos, + byte[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (byte) src[srcPos++]; + } + } + + /** + * Copy from an array of longs to array of bytes. + * + * The values will be cast to byte. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(long[] src, byte[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of longs to array of shorts. + * + * The values will be cast to short. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(long[] src, int srcPos, + short[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (short) src[srcPos++]; + } + } + + /** + * Copy from an array of longs to array of shorts. + * + * The values will be cast to short. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(long[] src, short[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of longs to array of ints. + * + * The values will be cast to int. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(long[] src, int srcPos, + int[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (int) src[srcPos++]; + } + } + + /** + * Copy from an array of longs to array of ints. + * + * The values will be cast to int. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(long[] src, int[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of longs to array of floats. + * + * The values will be cast to float. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(long[] src, int srcPos, + float[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (float) src[srcPos++]; + } + } + + /** + * Copy from an array of longs to array of floats. + * + * The values will be cast to float. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(long[] src, float[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of longs to array of doubles. + * + * The values will be cast to double. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(long[] src, int srcPos, + double[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (double) src[srcPos++]; + } + } + + /** + * Copy from an array of longs to array of doubles. + * + * The values will be cast to double. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(long[] src, double[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of floats to array of bytes. + * + * The values will be cast to byte. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(float[] src, int srcPos, + byte[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (byte) src[srcPos++]; + } + } + + /** + * Copy from an array of floats to array of bytes. + * + * The values will be cast to byte. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(float[] src, byte[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of floats to array of shorts. + * + * The values will be cast to short. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(float[] src, int srcPos, + short[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (short) src[srcPos++]; + } + } + + /** + * Copy from an array of floats to array of shorts. + * + * The values will be cast to short. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(float[] src, short[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of floats to array of ints. + * + * The values will be cast to int. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(float[] src, int srcPos, + int[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (int) src[srcPos++]; + } + } + + /** + * Copy from an array of floats to array of ints. + * + * The values will be cast to int. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(float[] src, int[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of floats to array of longs. + * + * The values will be cast to long. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(float[] src, int srcPos, + long[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (long) src[srcPos++]; + } + } + + /** + * Copy from an array of floats to array of longs. + * + * The values will be cast to long. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(float[] src, long[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of floats to array of doubles. + * + * The values will be cast to double. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(float[] src, int srcPos, + double[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (double) src[srcPos++]; + } + } + + /** + * Copy from an array of floats to array of doubles. + * + * The values will be cast to double. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(float[] src, double[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of doubles to array of bytes. + * + * The values will be cast to byte. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(double[] src, int srcPos, + byte[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (byte) src[srcPos++]; + } + } + + /** + * Copy from an array of doubles to array of bytes. + * + * The values will be cast to byte. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(double[] src, byte[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of doubles to array of shorts. + * + * The values will be cast to short. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(double[] src, int srcPos, + short[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (short) src[srcPos++]; + } + } + + /** + * Copy from an array of doubles to array of shorts. + * + * The values will be cast to short. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(double[] src, short[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of doubles to array of ints. + * + * The values will be cast to int. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(double[] src, int srcPos, + int[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (int) src[srcPos++]; + } + } + + /** + * Copy from an array of doubles to array of ints. + * + * The values will be cast to int. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(double[] src, int[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of doubles to array of longs. + * + * The values will be cast to long. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(double[] src, int srcPos, + long[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (long) src[srcPos++]; + } + } + + /** + * Copy from an array of doubles to array of longs. + * + * The values will be cast to long. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(double[] src, long[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Copy from an array of doubles to array of floats. + * + * The values will be cast to float. + * + * If the positions or lengths specified are out of range then an + * IndexOutOfBoundsException is thrown and the destination is not + * modified. + * + * @param src + * the source array. + * @param srcPos + * starting position in the source array. + * @param dst + * the destination array. + * @param dstPos + * starting position in the destination data. + * @param length + * the number of array elements to be copied. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(double[] src, int srcPos, + float[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (float) src[srcPos++]; + } + } + + /** + * Copy from an array of doubles to array of floats. + * + * The values will be cast to float. + * + * @param src + * the source array. + * @param dst + * the destination array. + * @throws IndexOutOfBoundsException + * if copying would cause access of data outside array bounds. + * @throws NullPointerException + * if either src or dest is + * null. + */ + public static void copy(double[] src, float[] dst) { + copy(src, 0, dst, 0, dst.length); + } + + /** + * Throws an {@link IndexOutOfBoundsException} if the arguments + * would result in an array copy that would go out of bounds. + */ + private static void checkCopy(int srcLen, int srcPos, + int dstLen, int dstPos, int length) + { + if (srcPos < 0) { + throw new IndexOutOfBoundsException("srcPos < 0"); + } + + if (dstPos < 0) { + throw new IndexOutOfBoundsException("dstPos < 0"); + } + + if (length < 0) { + throw new IndexOutOfBoundsException("length < 0"); + } + + if (srcPos + length > srcLen) { + throw new IndexOutOfBoundsException("srcPos + length > src.length"); + } + + if (dstPos + length > dstLen) { + throw new IndexOutOfBoundsException("dstPos + length > dst.length"); + } + } +} diff --git a/Annotation/src/ie/dcu/array/Filter$Byte.class b/Annotation/src/ie/dcu/array/Filter$Byte.class new file mode 100644 index 0000000..bdcc8ab Binary files /dev/null and b/Annotation/src/ie/dcu/array/Filter$Byte.class differ diff --git a/Annotation/src/ie/dcu/array/Filter$Double.class b/Annotation/src/ie/dcu/array/Filter$Double.class new file mode 100644 index 0000000..d447605 Binary files /dev/null and b/Annotation/src/ie/dcu/array/Filter$Double.class differ diff --git a/Annotation/src/ie/dcu/array/Filter$Float.class b/Annotation/src/ie/dcu/array/Filter$Float.class new file mode 100644 index 0000000..27da8a0 Binary files /dev/null and b/Annotation/src/ie/dcu/array/Filter$Float.class differ diff --git a/Annotation/src/ie/dcu/array/Filter$Integer.class b/Annotation/src/ie/dcu/array/Filter$Integer.class new file mode 100644 index 0000000..d936b83 Binary files /dev/null and b/Annotation/src/ie/dcu/array/Filter$Integer.class differ diff --git a/Annotation/src/ie/dcu/array/Filter$Long.class b/Annotation/src/ie/dcu/array/Filter$Long.class new file mode 100644 index 0000000..17c390d Binary files /dev/null and b/Annotation/src/ie/dcu/array/Filter$Long.class differ diff --git a/Annotation/src/ie/dcu/array/Filter$Short.class b/Annotation/src/ie/dcu/array/Filter$Short.class new file mode 100644 index 0000000..d0e77c5 Binary files /dev/null and b/Annotation/src/ie/dcu/array/Filter$Short.class differ diff --git a/Annotation/src/ie/dcu/array/Filter.class b/Annotation/src/ie/dcu/array/Filter.class new file mode 100644 index 0000000..0272591 Binary files /dev/null and b/Annotation/src/ie/dcu/array/Filter.class differ diff --git a/Annotation/src/ie/dcu/array/Filter.java b/Annotation/src/ie/dcu/array/Filter.java new file mode 100644 index 0000000..fad522b --- /dev/null +++ b/Annotation/src/ie/dcu/array/Filter.java @@ -0,0 +1,116 @@ +package ie.dcu.array; + +/** + * Interfaces for filters + * + * @author Kevin McGuinness + */ +public interface Filter { + + /** + * Returns true if the given value should be retained. + * + * @param object + * An object. + * @return + * true if the value should be retained. + */ + public boolean retain(Object object); + + + /** + * An byte filter. + */ + public interface Byte { + + /** + * Returns true if the given value should be retained. + * + * @param value + * An byte value. + * @return + * true if the value should be retained. + */ + public boolean retain(byte value); + } + + /** + * An short filter. + */ + public interface Short { + + /** + * Returns true if the given value should be retained. + * + * @param value + * An short value. + * @return + * true if the value should be retained. + */ + public boolean retain(short value); + } + + /** + * An int filter. + */ + public interface Integer { + + /** + * Returns true if the given value should be retained. + * + * @param value + * An int value. + * @return + * true if the value should be retained. + */ + public boolean retain(int value); + } + + /** + * An long filter. + */ + public interface Long { + + /** + * Returns true if the given value should be retained. + * + * @param value + * An long value. + * @return + * true if the value should be retained. + */ + public boolean retain(long value); + } + + /** + * An float filter. + */ + public interface Float { + + /** + * Returns true if the given value should be retained. + * + * @param value + * An float value. + * @return + * true if the value should be retained. + */ + public boolean retain(float value); + } + + /** + * An double filter. + */ + public interface Double { + + /** + * Returns true if the given value should be retained. + * + * @param value + * An double value. + * @return + * true if the value should be retained. + */ + public boolean retain(double value); + } +} diff --git a/Annotation/src/ie/dcu/array/Reduction$Double.class b/Annotation/src/ie/dcu/array/Reduction$Double.class new file mode 100644 index 0000000..c9a4a09 Binary files /dev/null and b/Annotation/src/ie/dcu/array/Reduction$Double.class differ diff --git a/Annotation/src/ie/dcu/array/Reduction$Long.class b/Annotation/src/ie/dcu/array/Reduction$Long.class new file mode 100644 index 0000000..7c74f1f Binary files /dev/null and b/Annotation/src/ie/dcu/array/Reduction$Long.class differ diff --git a/Annotation/src/ie/dcu/array/Reduction.class b/Annotation/src/ie/dcu/array/Reduction.class new file mode 100644 index 0000000..6c83c51 Binary files /dev/null and b/Annotation/src/ie/dcu/array/Reduction.class differ diff --git a/Annotation/src/ie/dcu/array/Reduction.java b/Annotation/src/ie/dcu/array/Reduction.java new file mode 100644 index 0000000..6e29fb4 --- /dev/null +++ b/Annotation/src/ie/dcu/array/Reduction.java @@ -0,0 +1,64 @@ +package ie.dcu.array; + +/** + * A reduce operation. + * + * @author Kevin McGuinness + */ +public interface Reduction { + + /** + * Perform a reduction. + * + * @param accumulator + * The accumulated value so far. + * @param value + * The next value in the array. + * @param index + * The index of the value in the array. + * @return + * The result of the reduction. + */ + public U reduce(U accumulator, T value, int index); + + + /** + * A long width reduction. + */ + public interface Long { + + /** + * Perform a reduction. + * + * @param accumulator + * The accumulated value so far. + * @param value + * The next value in the array. + * @param index + * The index of the value in the array. + * @return + * The result of the reduction. + */ + public long reduce(long accumulator, long value, int index); + } + + /** + * A double precision reduction. + */ + public interface Double { + + /** + * Perform a reduction. + * + * @param accumulator + * The accumulated value so far. + * @param value + * The next value in the array. + * @param index + * The index of the value in the array. + * @return + * The result of the reduction. + */ + public long reduce(double accumulator, double value, int index); + } +} diff --git a/Annotation/src/ie/dcu/auto/AutomationData$Listener.class b/Annotation/src/ie/dcu/auto/AutomationData$Listener.class new file mode 100644 index 0000000..2efff2e Binary files /dev/null and b/Annotation/src/ie/dcu/auto/AutomationData$Listener.class differ diff --git a/Annotation/src/ie/dcu/auto/AutomationData.class b/Annotation/src/ie/dcu/auto/AutomationData.class new file mode 100644 index 0000000..c0785af Binary files /dev/null and b/Annotation/src/ie/dcu/auto/AutomationData.class differ diff --git a/Annotation/src/ie/dcu/auto/AutomationData.java b/Annotation/src/ie/dcu/auto/AutomationData.java new file mode 100644 index 0000000..0eb9b8c --- /dev/null +++ b/Annotation/src/ie/dcu/auto/AutomationData.java @@ -0,0 +1,369 @@ +package ie.dcu.auto; + +import ie.dcu.auto.automator.*; +import ie.dcu.eval.*; +import ie.dcu.matrix.ByteMatrix; +import ie.dcu.segment.*; + +import java.io.IOException; +import java.util.*; + +/** + * Container class for data needed for the automation. + * + * @author Kevin McGuinness + */ +public class AutomationData { + + public static interface Listener { + public void segmentationContextChanged(AutomationData data); + public void segmentationContextUpdated(AutomationData automationData); + public void groundTruthMaskChanged(AutomationData data); + public void foregroundErrorChanged(AutomationData data); + public void backgroundErrorChanged(AutomationData data); + public void segmenterChanged(AutomationData data); + public void evaluationMeasuresChanged(AutomationData data); + public void evaluationResultsAdded(AutomationData data); + public void evaluationResultsCleared(AutomationData data); + public void automatorStateChanged(AutomationData data); + public void logUpdated(AutomationData data, String message); + + } + + private SegmentationContext segmentationContext; + private SegmentationMask groundTruthMask; + private ByteMatrix foregroundError; + private ByteMatrix backgroundError; + private EvaluationResults evaluationResults; + private List evaluators; + private Segmenter segmenter; + private Automator automator; + private List listeners; + + public AutomationData() { + evaluators = new LinkedList(); + listeners = new LinkedList(); + evaluationResults = new EvaluationResults(); + automator = new DeterministicAutomator(this); + } + + public void setAutomator(Automator automator) { + if (automator == null) { + throw new IllegalArgumentException(); + } + + // Reset old automator + this.automator.reset(); + + // Set new automator + this.automator = automator; + + // Reset new automator + this.automator.reset(); + } + + public void dispose() { + listeners.clear(); + evaluators.clear(); + setSegmentationContext(null); + } + + public void addDefaultEvaluators() { + addEvaluator(new BestEvaluator()); + } + + public void addEvaluator(Evaluator e) { + evaluators.add(e); + updateEvaluationMeasures(); + } + + public void removeEvaluator(Evaluator e) { + evaluators.remove(e); + updateEvaluationMeasures(); + } + + public List getEvaluators() { + return Collections.unmodifiableList(evaluators); + } + + public SegmentationContext getSegmentationContext() { + return segmentationContext; + } + + public void setSegmentationContext(SegmentationContext context) { + if (segmentationContext != context) { + + // Tidy up + if (segmentationContext != null) { + + if (segmenter != null) { + segmenter.finish(segmentationContext); + } + + if (!segmentationContext.isDisposed()) { + segmentationContext.dispose(); + } + + segmentationContext = null; + } + + // Set + this.segmentationContext = context; + fireSegmentationContextChanged(); + } + } + + public void setSegmenter(Segmenter segmenter) { + if (this.segmenter != segmenter) { + + // Tidy up + if (this.segmenter != null) { + if (segmentationContext != null) { + this.segmenter.finish(segmentationContext); + } + this.segmenter = null; + } + + this.segmenter = segmenter; + this.automator.reset(); + fireSegmenterChanged(); + } + } + + public Segmenter getSegmenter() { + return segmenter; + } + + public SegmentationMask getGroundTruthMask() { + return groundTruthMask; + } + + public void setGroundTruthMask(SegmentationMask mask) { + if (this.groundTruthMask != mask) { + this.groundTruthMask = mask; + fireGroundTruthMaskChanged(); + } + } + + public ByteMatrix getForegroundError() { + return foregroundError; + } + + public void setForegroundError(ByteMatrix error) { + if (this.foregroundError != error) { + this.foregroundError = error; + fireForegroundErrorChanged(); + } + } + + public ByteMatrix getBackgroundError() { + return backgroundError; + } + + public void setBackgroundError(ByteMatrix error) { + if (this.backgroundError != error) { + this.backgroundError = error; + fireBackgroundErrorChanged(); + } + } + + public void clearEvaluationResults() { + if (evaluationResults.getResultCount() > 0) { + evaluationResults.clearResults(); + fireEvaluationResultsCleared(); + } + } + + private void updateEvaluationMeasures() { + List headings = new ArrayList(); + for (Evaluator e : evaluators) { + String[] measures = e.getMeasures(); + for (String m : measures) { + headings.add(m); + } + } + + String[] measures = headings.toArray(new String[headings.size()]); + setEvaluationMeasures(measures); + } + + public void evaluate() { + SegmentationMask mask = segmentationContext.getMask(); + + double[] values = new double[evaluationResults.getMeasureCount()]; + for (Evaluator e : evaluators) { + e.run(mask, groundTruthMask); + + String[] measures = e.getMeasures(); + for (String m : measures) { + int idx = evaluationResults.indexOfMeasure(m); + values[idx] = e.getMeasure(m); + } + } + + addEvaluationResult(values); + } + + private void addEvaluationResult(double[] result) { + evaluationResults.addResults(result); + fireEvaluationResultAdded(); + } + + private void setEvaluationMeasures(String[] measures) { + clearEvaluationResults(); + evaluationResults.setMeasures(measures); + fireEvaluationMeasuresChanged(); + } + + public EvaluationResults getEvaluationResults() { + return evaluationResults; + } + + public Automator getAutomator() { + return automator; + } + + public void load(AutomationInput input) throws IOException { + SegmentationContext ctx = SegmentationContext.create(input.imageFile); + SegmentationMask mask = SegmentationMask.read(input.groundTruthFile); + + if (ctx.getBounds().equals(mask.getBounds())) { + + clearEvaluationResults(); + setSegmentationContext(ctx); + setGroundTruthMask(mask); + automator.reset(); + + + } else { + ctx.dispose(); + throw new IOException("Images are not the same size"); + } + } + + public void updateSegmentationError() { + + SegmentationMask mask = segmentationContext.getMask(); + + int rows = groundTruthMask.height; + int cols = groundTruthMask.width; + + if (foregroundError == null || + foregroundError.cols != cols || + foregroundError.rows != rows) + { + foregroundError = new ByteMatrix(rows, cols); + } + + if (backgroundError == null || + backgroundError.cols != cols || + backgroundError.rows != rows) + { + backgroundError = new ByteMatrix(rows, cols); + } + + foregroundError.fill(0); + backgroundError.fill(0); + + for (int i = 0; i < rows; i++) { + int k = i * cols; + + for (int j = 0; j < cols; j++, k++) { + int v = groundTruthMask.values[k]; + if (v != mask.values[k]) { + switch (v) { + case SegmentationMask.FOREGROUND: + foregroundError.values[k] = Constants.ERROR_VALUE; + break; + case SegmentationMask.BACKGROUND: + backgroundError.values[k] = Constants.ERROR_VALUE; + break; + } + + } + } + } + + fireForegroundErrorChanged(); + fireBackgroundErrorChanged(); + } + + public void logActivity(String message, Object ... args) { + String log = String.format(message, args) + "\n"; + fireLogUpdated(log); + } + + private void fireLogUpdated(String message) { + for (Listener listener : listeners) { + listener.logUpdated(this, message); + } + } + + private void fireSegmenterChanged() { + for (Listener listener : listeners) { + listener.segmenterChanged(this); + } + } + + private void fireForegroundErrorChanged() { + for (Listener listener : listeners) { + listener.foregroundErrorChanged(this); + } + } + + private void fireBackgroundErrorChanged() { + for (Listener listener : listeners) { + listener.backgroundErrorChanged(this); + } + } + + private void fireSegmentationContextChanged() { + for (Listener listener : listeners) { + listener.segmentationContextChanged(this); + } + } + + public void fireSegmentationContextUpdated() { + for (Listener listener : listeners) { + listener.segmentationContextUpdated(this); + } + } + + private void fireGroundTruthMaskChanged() { + for (Listener listener : listeners) { + listener.groundTruthMaskChanged(this); + } + } + + private void fireEvaluationMeasuresChanged() { + for (Listener listener : listeners) { + listener.evaluationMeasuresChanged(this); + } + } + + private void fireEvaluationResultAdded() { + for (Listener listener : listeners) { + listener.evaluationResultsAdded(this); + } + } + + private void fireEvaluationResultsCleared() { + for (Listener listener : listeners) { + listener.evaluationResultsCleared(this); + } + } + + public void fireAutomatorStateChanged() { + for (Listener listener : listeners) { + listener.automatorStateChanged(this); + } + } + + public void addListener(Listener listener) { + listeners.add(listener); + } + + public void removeListener(Listener listener) { + listeners.remove(listener); + } +} diff --git a/Annotation/src/ie/dcu/auto/AutomationDataAdapter.class b/Annotation/src/ie/dcu/auto/AutomationDataAdapter.class new file mode 100644 index 0000000..2412fd9 Binary files /dev/null and b/Annotation/src/ie/dcu/auto/AutomationDataAdapter.class differ diff --git a/Annotation/src/ie/dcu/auto/AutomationDataAdapter.java b/Annotation/src/ie/dcu/auto/AutomationDataAdapter.java new file mode 100644 index 0000000..6072343 --- /dev/null +++ b/Annotation/src/ie/dcu/auto/AutomationDataAdapter.java @@ -0,0 +1,42 @@ +package ie.dcu.auto; + +/** + * Convenience class for listeners who are only interested in some events + * + * @author Kevin McGuinness + */ +public class AutomationDataAdapter implements AutomationData.Listener { + + public void automatorStateChanged(AutomationData data) { + } + + public void backgroundErrorChanged(AutomationData data) { + } + + public void evaluationMeasuresChanged(AutomationData data) { + } + + public void evaluationResultsAdded(AutomationData data) { + } + + public void evaluationResultsCleared(AutomationData data) { + } + + public void foregroundErrorChanged(AutomationData data) { + } + + public void groundTruthMaskChanged(AutomationData data) { + } + + public void logUpdated(AutomationData data, String message) { + } + + public void segmentationContextChanged(AutomationData data) { + } + + public void segmentationContextUpdated(AutomationData automationData) { + } + + public void segmenterChanged(AutomationData data) { + } +} diff --git a/Annotation/src/ie/dcu/auto/AutomationInput.class b/Annotation/src/ie/dcu/auto/AutomationInput.class new file mode 100644 index 0000000..917abeb Binary files /dev/null and b/Annotation/src/ie/dcu/auto/AutomationInput.class differ diff --git a/Annotation/src/ie/dcu/auto/AutomationInput.java b/Annotation/src/ie/dcu/auto/AutomationInput.java new file mode 100644 index 0000000..ccad68e --- /dev/null +++ b/Annotation/src/ie/dcu/auto/AutomationInput.java @@ -0,0 +1,102 @@ +package ie.dcu.auto; + +import java.io.File; + +/** + * Immutable class encapsulating an input for the automation. + * + * @author Kevin McGuinness + */ +public class AutomationInput { + + /** + * The input image file. + */ + public final File imageFile; + + /** + * The input ground-truth mask file. + */ + public final File groundTruthFile; + + /** + * Create an automation input with the given image and ground + * truth file. + * + * @param imageFile + * The image file (cannot be null). + * @param groundTruthFile + * The ground-truth mask file (cannot be null). + */ + public AutomationInput(File imageFile, File groundTruthFile) { + + if (imageFile == null) { + throw new IllegalArgumentException("imageFile == null"); + } + + if (groundTruthFile == null) { + throw new IllegalArgumentException("groundTruthFile == null"); + } + + this.imageFile = imageFile; + this.groundTruthFile = groundTruthFile; + } + + /** + * Returns true if both the image and ground truth files exist. + */ + public boolean filesExist() { + return imageFile.isFile() && groundTruthFile.isFile(); + } + + /** + * Returns the image file. + */ + public File getImageFile() { + return imageFile; + } + + /** + * Returns the ground-truth file. + */ + public File getGroundTruthFile() { + return groundTruthFile; + } + + /** + * Returns a deep copy of the object. + */ + @Override + protected AutomationInput clone() { + return new AutomationInput(imageFile, groundTruthFile); + } + + /** + * Compare for equality. + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof AutomationInput) { + AutomationInput x = (AutomationInput) obj; + return x.imageFile.equals(imageFile) && + x.groundTruthFile.equals(groundTruthFile); + } + return false; + } + + /** + * Hash code override. + */ + @Override + public int hashCode() { + return imageFile.hashCode() + groundTruthFile.hashCode(); + } + + /** + * Returns a string representation + */ + @Override + public String toString() { + return imageFile.getName() + "," + groundTruthFile.getName(); + } +} diff --git a/Annotation/src/ie/dcu/auto/Constants.class b/Annotation/src/ie/dcu/auto/Constants.class new file mode 100644 index 0000000..9019094 Binary files /dev/null and b/Annotation/src/ie/dcu/auto/Constants.class differ diff --git a/Annotation/src/ie/dcu/auto/Constants.java b/Annotation/src/ie/dcu/auto/Constants.java new file mode 100644 index 0000000..2debd37 --- /dev/null +++ b/Annotation/src/ie/dcu/auto/Constants.java @@ -0,0 +1,5 @@ +package ie.dcu.auto; + +public interface Constants { + final byte ERROR_VALUE = (byte) 0xff; +} diff --git a/Annotation/src/ie/dcu/auto/EvaluationResults$Item.class b/Annotation/src/ie/dcu/auto/EvaluationResults$Item.class new file mode 100644 index 0000000..093677d Binary files /dev/null and b/Annotation/src/ie/dcu/auto/EvaluationResults$Item.class differ diff --git a/Annotation/src/ie/dcu/auto/EvaluationResults.class b/Annotation/src/ie/dcu/auto/EvaluationResults.class new file mode 100644 index 0000000..23618aa Binary files /dev/null and b/Annotation/src/ie/dcu/auto/EvaluationResults.class differ diff --git a/Annotation/src/ie/dcu/auto/EvaluationResults.java b/Annotation/src/ie/dcu/auto/EvaluationResults.java new file mode 100644 index 0000000..1200990 --- /dev/null +++ b/Annotation/src/ie/dcu/auto/EvaluationResults.java @@ -0,0 +1,66 @@ +package ie.dcu.auto; + +import java.util.*; + +public class EvaluationResults { + + private static class Item { + final double[] values; + + public Item(double[] values) { + this.values = values.clone(); + } + }; + + private String[] measures; + private final List results; + + public EvaluationResults() { + this.measures = new String[0]; + this.results = new ArrayList(); + } + + void setMeasures(String[] measures) { + if (this.measures != measures) { + clearResults(); + this.measures = measures.clone(); + } + } + + public String[] getMeasures() { + return measures; + } + + public int getMeasureCount() { + return measures.length; + } + + public int indexOfMeasure(String measure) { + for (int i = 0; i < measures.length; i++) { + if (measures[i].equals(measure)) { + return i; + } + } + return -1; + } + + void clearResults() { + results.clear(); + } + + void addResults(double[] results) { + if (results.length != measures.length) { + throw new IllegalArgumentException(); + } + + this.results.add(new Item(results)); + } + + public double[] getResults(int idx) { + return results.get(idx).values; + } + + public int getResultCount() { + return results.size(); + } +} diff --git a/Annotation/src/ie/dcu/auto/MaximaLocator.class b/Annotation/src/ie/dcu/auto/MaximaLocator.class new file mode 100644 index 0000000..884bb80 Binary files /dev/null and b/Annotation/src/ie/dcu/auto/MaximaLocator.class differ diff --git a/Annotation/src/ie/dcu/auto/MaximaLocator.java b/Annotation/src/ie/dcu/auto/MaximaLocator.java new file mode 100644 index 0000000..72fb9c9 --- /dev/null +++ b/Annotation/src/ie/dcu/auto/MaximaLocator.java @@ -0,0 +1,42 @@ +package ie.dcu.auto; + +import ie.dcu.matrix.*; + +import java.util.*; + +public class MaximaLocator { + + private final IntMatrix matrix; + private int maximum; + + public MaximaLocator(IntMatrix matrix) { + this.matrix = matrix; + this.maximum = Integer.MIN_VALUE; + } + + public int getMaximum() { + return maximum; + } + + public List findAll(int min) { + maximum = matrix.maxValue(); + + if (maximum < min) { + return Collections.emptyList(); + } + + List indices = new ArrayList(); + + for (int i = 0; i < matrix.rows; i++) { + int k = i * matrix.cols; + + for (int j = 0; j < matrix.cols; j++, k++) { + if (matrix.values[k] == maximum) { + indices.add(new Index2D(i, j)); + } + } + } + + return indices; + } +} diff --git a/Annotation/src/ie/dcu/auto/automator/AbstractAutomator.class b/Annotation/src/ie/dcu/auto/automator/AbstractAutomator.class new file mode 100644 index 0000000..b4dbf54 Binary files /dev/null and b/Annotation/src/ie/dcu/auto/automator/AbstractAutomator.class differ diff --git a/Annotation/src/ie/dcu/auto/automator/AbstractAutomator.java b/Annotation/src/ie/dcu/auto/automator/AbstractAutomator.java new file mode 100644 index 0000000..09c8f41 --- /dev/null +++ b/Annotation/src/ie/dcu/auto/automator/AbstractAutomator.java @@ -0,0 +1,161 @@ +package ie.dcu.auto.automator; + +import ie.dcu.auto.AutomationData; +import ie.dcu.matrix.*; +import ie.dcu.segment.*; +import ie.dcu.segment.annotate.AnnotationManager; + +import org.eclipse.swt.graphics.Point; + +/** + * Handles the grunt work of the automator (maintaining state, sending + * notifications, and so forth). + * + * Subclasses just need to implement {@link #doReset()}, {@link #doStart()}, and + * {@link #doStep()}. + * + * + * @author Kevin McGuinness + */ +public abstract class AbstractAutomator implements Automator { + private final AutomationData data; + private boolean done; + private int maxSteps; + private int step; + + public AbstractAutomator(AutomationData data) { + this.data = data; + this.done = false; + this.maxSteps = DEFAULT_MAX_STEPS; + this.step = -1; + } + + public void setMaxSteps(int maxSteps) { + if (maxSteps < 0) { + throw new IllegalArgumentException(); + } + this.maxSteps = maxSteps; + } + + public int getMaxSteps() { + return maxSteps; + } + + public int getStep() { + return step; + } + + public boolean canReset() { + return hasSegmentationContext(); + } + + public boolean canStart() { + return step == 0 && hasSegmentationContext(); + } + + public boolean canStep() { + return step > 0 && !done && hasSegmentationContext() && step < maxSteps; + } + + public void reset() { + if (canReset()) { + doReset(); + getSegmenter().finish(getSegmentationContext()); + getAnnotations().clear(); + getSegmentationContext().getMask().clear(); + getSegmenter().init(getSegmentationContext()); + step = 0; + done = false; + data.clearEvaluationResults(); + data.updateSegmentationError(); + data.fireAutomatorStateChanged(); + data.fireSegmentationContextUpdated(); + } + } + + public void start() { + if (canStart()) { + doStart(); + + // Update segmentation + getSegmenter().update(getSegmentationContext()); + + // Evaluate + data.evaluate(); + + // Set step + step = 1; + + // Notify + data.updateSegmentationError(); + data.fireAutomatorStateChanged(); + data.fireSegmentationContextUpdated(); + } + } + + public void step() { + if (canStep()) { + doStep(); + + // Update segmentation + getSegmenter().update(getSegmentationContext()); + + // Evaluate + data.evaluate(); + + // Increment step + step++; + + if (done || step == maxSteps) { + getSegmenter().finish(getSegmentationContext()); + } + + // Notify + data.updateSegmentationError(); + data.fireAutomatorStateChanged(); + data.fireSegmentationContextUpdated(); + } + } + + private boolean hasSegmentationContext() { + return data.getSegmentationContext() != null; + } + + private Segmenter getSegmenter() { + return data.getSegmenter(); + } + + private SegmentationContext getSegmentationContext() { + return data.getSegmentationContext(); + } + + protected AnnotationManager getAnnotations() { + return data.getSegmentationContext().getAnnotations(); + } + + protected ByteMatrix getForegroundError() { + return data.getForegroundError(); + } + + protected ByteMatrix getBackgroundError() { + return data.getBackgroundError(); + } + + protected void log(String format, Object... args) { + data.logActivity(String.format(format, args)); + } + + protected void setDone(boolean done) { + this.done = done; + } + + protected static Point getSwtPointForIndex(Index2D index) { + return new Point(index.j, index.i); + } + + protected abstract void doReset(); + + protected abstract void doStart(); + + protected abstract void doStep(); +} diff --git a/Annotation/src/ie/dcu/auto/automator/Automator.class b/Annotation/src/ie/dcu/auto/automator/Automator.class new file mode 100644 index 0000000..eca6f16 Binary files /dev/null and b/Annotation/src/ie/dcu/auto/automator/Automator.class differ diff --git a/Annotation/src/ie/dcu/auto/automator/Automator.java b/Annotation/src/ie/dcu/auto/automator/Automator.java new file mode 100644 index 0000000..aba621b --- /dev/null +++ b/Annotation/src/ie/dcu/auto/automator/Automator.java @@ -0,0 +1,64 @@ +package ie.dcu.auto.automator; + +/** + * Automates the evaluation of interactive segmentation algorithms + * + * @author Kevin McGuinness + */ +public interface Automator { + + /** + * The maximum brush size that an automator may use. + */ + public static final int MAX_BRUSH_SIZE = 20; + + /** + * The default maximum number of steps to use. + */ + public static final int DEFAULT_MAX_STEPS = 200; + + /** + * Returns the current step. + */ + public int getStep(); + + /** + * Returns the max number of steps the automator will take. + */ + public int getMaxSteps(); + + /** + * Set the max number of steps the automator will take. + */ + public void setMaxSteps(int maxSteps); + + /** + * Returns true if the automator can currently be reset. + */ + public boolean canReset(); + + /** + * Reset the automator. + */ + public void reset(); + + /** + * Returns true if the automator can currently be started. + */ + public boolean canStart(); + + /** + * Start the automator. + */ + public void start(); + + /** + * Returns true if a step in the automation can be taken. + */ + public boolean canStep(); + + /** + * Take the next step in the automation procedure. + */ + public void step(); +} \ No newline at end of file diff --git a/Annotation/src/ie/dcu/auto/automator/AutomatorFactory.class b/Annotation/src/ie/dcu/auto/automator/AutomatorFactory.class new file mode 100644 index 0000000..a397f6a Binary files /dev/null and b/Annotation/src/ie/dcu/auto/automator/AutomatorFactory.class differ diff --git a/Annotation/src/ie/dcu/auto/automator/AutomatorFactory.java b/Annotation/src/ie/dcu/auto/automator/AutomatorFactory.java new file mode 100644 index 0000000..8798af1 --- /dev/null +++ b/Annotation/src/ie/dcu/auto/automator/AutomatorFactory.java @@ -0,0 +1,91 @@ +package ie.dcu.auto.automator; + +import ie.dcu.auto.AutomationData; + +import java.lang.reflect.*; +import java.util.*; + +/** + * Creates automator instances. + * + * @author Kevin McGuinness + */ +public class AutomatorFactory { + + public static final String STRATEGY1 = "Strategy 1 (Deterministic)"; + public static final String STRATEGY2 = "Strategy 2 (Probabilistic)"; + public static final String STRATEGY3 = "Strategy 3 (Probabilistic)"; + public static final String STRATEGY4 = "Strategy 4 (Probabilistic)"; + + private final Map> automators; + private static AutomatorFactory instance; + + private AutomatorFactory() { + automators = new HashMap>(); + automators.put(STRATEGY1, DeterministicAutomator.class); + automators.put(STRATEGY2, NonDeterministicAutomator1.class); + automators.put(STRATEGY3, NonDeterministicAutomator2.class); + automators.put(STRATEGY4, NonDeterministicAutomator3.class); + } + + public Automator createAutomator(String strategy, AutomationData data) { + + try { + Class clazz = automators.get(strategy); + if (clazz != null) { + Constructor ctor = + clazz.getConstructor(AutomationData.class); + return ctor.newInstance(data); + } else { + throw new IllegalArgumentException( + "no such strategy: " + strategy); + } + + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public boolean hasAutomator(String strategy) { + return automators.containsKey(strategy); + } + + public Set getAvailableStrategies() { + return Collections.unmodifiableSet(automators.keySet()); + } + + public boolean isNonDeterministic(String strategy) { + if (hasAutomator(strategy)) { + Class clazz = automators.get(strategy); + try { + Method method = clazz.getMethod("isNonDeterministic"); + return (Boolean) method.invoke(null); + + } catch (SecurityException e) { + return false; + } catch (NoSuchMethodException e) { + return false; + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + return false; + } + + public static AutomatorFactory getInstance() { + if (instance == null) { + instance = new AutomatorFactory(); + } + return instance; + } +} diff --git a/Annotation/src/ie/dcu/auto/automator/DeterministicAutomator.class b/Annotation/src/ie/dcu/auto/automator/DeterministicAutomator.class new file mode 100644 index 0000000..5319361 Binary files /dev/null and b/Annotation/src/ie/dcu/auto/automator/DeterministicAutomator.class differ diff --git a/Annotation/src/ie/dcu/auto/automator/DeterministicAutomator.java b/Annotation/src/ie/dcu/auto/automator/DeterministicAutomator.java new file mode 100644 index 0000000..8270381 --- /dev/null +++ b/Annotation/src/ie/dcu/auto/automator/DeterministicAutomator.java @@ -0,0 +1,156 @@ +package ie.dcu.auto.automator; + +import ie.dcu.auto.*; +import ie.dcu.image.dt.DistanceTransform; +import ie.dcu.matrix.*; +import ie.dcu.segment.annotate.*; + +import java.util.*; + +import org.eclipse.swt.graphics.Point; + +/** + * Automates the evaluation of interactive segmentation algorithms using + * a simple deterministic method. + * + * @author Kevin McGuinness + */ +public class DeterministicAutomator extends AbstractAutomator implements Automator { + private final Set seeds; + + public DeterministicAutomator(AutomationData data) { + super(data); + this.seeds = new HashSet(); + } + + protected void doReset() { + seeds.clear(); + } + + protected void doStart() { + + // Get error + ByteMatrix fgError = getForegroundError(); + ByteMatrix bgError = getBackgroundError(); + + // DT + IntMatrix fgDT = distanceTransform(fgError); + IntMatrix bgDT = distanceTransform(bgError); + + // Maxima + MaximaLocator fgLocator = new MaximaLocator(fgDT); + List fgMaxima = fgLocator.findAll(2); + + MaximaLocator bgLocator = new MaximaLocator(bgDT); + List bgMaxima = bgLocator.findAll(2); + + // Add seeds + if (fgMaxima.size() > 0 && bgMaxima.size() > 0) { + addForegroundSeeds(fgMaxima, fgLocator.getMaximum()); + addBackgroundSeeds(bgMaxima, bgLocator.getMaximum()); + } else if (fgMaxima.size() > 0) { + addForegroundSeeds(fgMaxima, fgLocator.getMaximum()); + } else if (bgMaxima.size() > 0) { + addBackgroundSeeds(bgMaxima, bgLocator.getMaximum()); + } else { + log("Automation complete"); + setDone(true); + } + } + + protected void doStep() { + + // Get error + ByteMatrix fgError = getForegroundError(); + ByteMatrix bgError = getBackgroundError(); + + // DT + IntMatrix fgDT = distanceTransform(fgError); + IntMatrix bgDT = distanceTransform(bgError); + + // Maxima + MaximaLocator fgLocator = new MaximaLocator(fgDT); + List fgMaxima = fgLocator.findAll(2); + + MaximaLocator bgLocator = new MaximaLocator(bgDT); + List bgMaxima = bgLocator.findAll(2); + + log("Found %d potential foreground seeds", fgMaxima.size()); + log("Found %d potential background seeds", bgMaxima.size()); + + // Remove previously selected seeds + removeSelectedSeeds(fgMaxima); + removeSelectedSeeds(bgMaxima); + + // Add seeds + if (fgMaxima.size() > 0 && bgMaxima.size() > 0) { + + if (fgLocator.getMaximum() >= bgLocator.getMaximum()) { + addForegroundSeeds(fgMaxima, fgLocator.getMaximum()); + } else { + addBackgroundSeeds(bgMaxima, bgLocator.getMaximum()); + } + + } else if (fgMaxima.size() > 0) { + addForegroundSeeds(fgMaxima, fgLocator.getMaximum()); + + } else if (bgMaxima.size() > 0) { + addBackgroundSeeds(bgMaxima, bgLocator.getMaximum()); + + } else { + log("Automation complete"); + setDone(true); + } + } + + private void removeSelectedSeeds(List seeds) { + Iterator iterator = seeds.iterator(); + + while (iterator.hasNext()) { + Index2D seed = iterator.next(); + if (this.seeds.contains(seed)) { + iterator.remove(); + } + } + } + + private void addBackgroundSeeds(List seeds, int maximum) { + double distance = Math.sqrt(maximum); + + log("Adding %d background seeds (distance: %f)", seeds.size(), distance); + + int size = (int) Math.min(distance/2, MAX_BRUSH_SIZE); + + AnnotationManager annotations = getAnnotations(); + for (Index2D seed : seeds) { + this.seeds.add(seed); + Point pt = getSwtPointForIndex(seed); + annotations.add(new Annotation(AnnotationType.Background, size, pt)); + } + } + + private void addForegroundSeeds(List seeds, int maximum) { + double distance = Math.sqrt(maximum); + + log("Adding %d foreground seeds (distance: %f)", seeds.size(), distance); + + int size = (int) Math.min(distance/2, MAX_BRUSH_SIZE); + + AnnotationManager annotations = getAnnotations(); + for (Index2D seed : seeds) { + this.seeds.add(seed); + Point pt = getSwtPointForIndex(seed); + annotations.add(new Annotation(AnnotationType.Foreground, size, pt)); + } + } + + private static IntMatrix distanceTransform(ByteMatrix error) { + DistanceTransform dt = new DistanceTransform(); + dt.init(error, Constants.ERROR_VALUE); + return dt.computeSquareTransform(); + } + + public static boolean isNonDeterministic() { + return false; + } +} diff --git a/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator1.class b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator1.class new file mode 100644 index 0000000..b689c7f Binary files /dev/null and b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator1.class differ diff --git a/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator1.java b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator1.java new file mode 100644 index 0000000..530f935 --- /dev/null +++ b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator1.java @@ -0,0 +1,141 @@ +package ie.dcu.auto.automator; + +import ie.dcu.auto.*; +import ie.dcu.image.dt.DistanceTransform; +import ie.dcu.matrix.*; +import ie.dcu.segment.annotate.*; +import ie.dcu.stats.InversionMethod; + +import java.util.*; + +import org.eclipse.swt.graphics.Point; + +/** + * Automates the evaluation of interactive segmentation algorithms using + * a simple non-deterministic method. + * + * @author Kevin McGuinness + */ +public class NonDeterministicAutomator1 + extends AbstractAutomator implements Automator +{ + private final Set seeds; + + public NonDeterministicAutomator1(AutomationData data) { + super(data); + this.seeds = new HashSet(); + } + + protected void doReset() { + seeds.clear(); + } + + protected void doStart() { + + // Distance transform + DoubleMatrix fgDT = distanceTransform(getForegroundError()); + DoubleMatrix bgDT = distanceTransform(getBackgroundError()); + + // Initialize foreground probability field + Index2D fgIndex = null; + if (nonzero(fgDT)) { + InversionMethod fgProb = new InversionMethod(fgDT.values); + fgIndex = fgDT.indexOf(fgProb.random()); + } + + // Initialize background probability field + Index2D bgIndex = null; + if (nonzero(bgDT)) { + InversionMethod bgProb = new InversionMethod(bgDT.values); + bgIndex = bgDT.indexOf(bgProb.random()); + } + + // Add seeds + if (fgIndex != null && bgIndex != null) { + addSeed(fgDT, fgIndex, AnnotationType.Foreground); + addSeed(bgDT, bgIndex, AnnotationType.Background); + } else if (fgIndex != null) { + addSeed(fgDT, fgIndex, AnnotationType.Foreground); + } else if (bgIndex != null) { + addSeed(bgDT, bgIndex, AnnotationType.Background); + } else { + log("Automation complete"); + setDone(true); + } + } + + protected void doStep() { + ByteMatrix fgError = getForegroundError(); + ByteMatrix bgError = getBackgroundError(); + + DoubleMatrix field = getProbabilityField(fgError, bgError); + if (field != null) { + InversionMethod rv = new InversionMethod(field.values); + Index2D seed = field.indexOf(rv.random()); + AnnotationType type = + (fgError.byteAt(seed) == Constants.ERROR_VALUE) ? + AnnotationType.Foreground : AnnotationType.Background; + addSeed(field, seed, type); + + } else { + log("Automation complete"); + setDone(true); + } + } + + private DoubleMatrix getProbabilityField(ByteMatrix fgError, ByteMatrix bgError) { + + // Distance transforms + DoubleMatrix fgDT = distanceTransform(fgError); + DoubleMatrix bgDT = distanceTransform(bgError); + + // Sum transforms + DoubleMatrix field = fgDT; + for (int i = 0; i < field.size; i++) { + field.values[i] += bgDT.values[i]; + } + + // Set probability of selected seeds to zero + for (Index2D seed : seeds) { + field.setDoubleAt(seed, 0.0); + } + + if (!isStoppingCriteriaSatisfied(field)) { + return field; + } + + return null; + } + + private void addSeed(DoubleMatrix dt, Index2D seed, AnnotationType type) { + double distance = dt.doubleAt(seed); + int size = (int) Math.min(distance/2, MAX_BRUSH_SIZE); + size = Math.max(size, 1); + Point pt = getSwtPointForIndex(seed); + getAnnotations().add(new Annotation(type, size, pt)); + seeds.add(seed); + } + + private static DoubleMatrix distanceTransform(ByteMatrix error) { + DistanceTransform dt = new DistanceTransform(); + dt.init(error, Constants.ERROR_VALUE); + return dt.computeTransform(); + } + + private static boolean isStoppingCriteriaSatisfied(DoubleMatrix dt) { + return dt.maxValue() < 2.0; + } + + private static boolean nonzero(DoubleMatrix matrix) { + for (int i = 0; i < matrix.size; i++) { + if (matrix.values[i] != 0) { + return true; + } + } + return false; + } + + public static boolean isNonDeterministic() { + return true; + } +} diff --git a/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator2.class b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator2.class new file mode 100644 index 0000000..2027b28 Binary files /dev/null and b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator2.class differ diff --git a/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator2.java b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator2.java new file mode 100644 index 0000000..161d33f --- /dev/null +++ b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator2.java @@ -0,0 +1,295 @@ +package ie.dcu.auto.automator; + +import static ie.dcu.auto.Constants.ERROR_VALUE; +import ie.dcu.auto.*; +import ie.dcu.graph.dijkstra.IntGraph; +import ie.dcu.image.dt.DistanceTransform; +import ie.dcu.matrix.*; +import ie.dcu.segment.annotate.*; +import ie.dcu.stats.InversionMethod; + +import java.util.*; + +import org.eclipse.swt.graphics.Point; + +/** + * Implementation of the more complex non-deterministic strategy for interactive + * segmentation evaluation. + * + * @author Kevin McGuinness + * + */ +public class NonDeterministicAutomator2 + extends AbstractAutomator implements Automator +{ + private final Set seeds; + + public NonDeterministicAutomator2(AutomationData data) { + super(data); + this.seeds = new HashSet(); + } + + @Override + protected void doReset() { + seeds.clear(); + } + + @Override + protected void doStart() { + ByteMatrix fgError = getForegroundError(); + ByteMatrix bgError = getBackgroundError(); + + // Distance transform + DoubleMatrix fgDT = distanceTransform(fgError); + DoubleMatrix bgDT = distanceTransform(bgError); + + // Initialize foreground probability field + List fgPath = createPath(fgError, fgDT); + List bgPath = createPath(bgError, bgDT); + + // Add seeds + if (fgPath != null && bgPath != null) { + addSeedPath(fgDT, fgPath, AnnotationType.Foreground); + addSeedPath(bgDT, bgPath, AnnotationType.Background); + } else if (fgPath != null) { + addSeedPath(fgDT, fgPath, AnnotationType.Foreground); + } else if (bgPath != null) { + addSeedPath(bgDT, bgPath, AnnotationType.Background); + } else { + log("Automation complete"); + setDone(true); + } + } + + @Override + protected void doStep() { + ByteMatrix fgError = getForegroundError(); + ByteMatrix bgError = getBackgroundError(); + + DoubleMatrix fgDT = distanceTransform(fgError); + DoubleMatrix bgDT = distanceTransform(bgError); + + DoubleMatrix field = getProbabilityField(fgDT, bgDT); + + if (field != null) { + InversionMethod rv = new InversionMethod(field.values); + int seed = rv.random(); + List path = null; + AnnotationType type; + + if (fgError.values[seed] == ERROR_VALUE) { + type = AnnotationType.Foreground; + path = createPath(fgError, fgDT, seed); + + } else { + type = AnnotationType.Background; + path = createPath(bgError, bgDT, seed); + } + + if (path != null) { + addSeedPath(field, path, type); + } else { + addSeed(field, seed, type); + } + + } else { + log("Automation complete"); + setDone(true); + } + } + + private void addSeed(DoubleMatrix field, int seed, AnnotationType type) { + log("Adding single seed"); + + Index2D index = field.indexOf(seed); + double distance = field.doubleAt(seed); + int size = (int) Math.min(distance/2, MAX_BRUSH_SIZE); + size = Math.max(size, 1); + Point pt = getSwtPointForIndex(index); + getAnnotations().add(new Annotation(type, size, pt)); + seeds.add(index); + } + + private void addSeedPath( + DoubleMatrix field, List path, AnnotationType type) { + + log("Adding seed path"); + + int size = MAX_BRUSH_SIZE; + for (int k : path) { + double distance = field.doubleAt(k); + size = (int) Math.min(size, distance/2); + } + + size = Math.max(size, 1); + + for (int k : path) { + Index2D index = field.indexOf(k); + Point pt = getSwtPointForIndex(index); + getAnnotations().add(new Annotation(type, size, pt)); + seeds.add(index); + } + } + + private List createPath(ByteMatrix error, DoubleMatrix dt) { + if (nonzero(dt)) { + + // Select random variable + InversionMethod field = new InversionMethod(dt.values); + int source = field.random(); + + // Create path + return createPath(error, dt, source); + } + + return null; + } + + private List createPath(ByteMatrix error, DoubleMatrix dt, int source) { + + // Build graph + IntGraph graph = buildGraph(error); + + // The graph may not contain the source pixel if it has no neighbors + if (graph.hasNode(source)) { + + // Ok, it does + graph.findPaths(source); + + // Mark inaccessible pixels with probability zero + for (int i = 0; i < dt.size; i++) { + if (!graph.hasNode(i)) { + dt.values[i] = 0.0; + } + } + + if (nonzero(dt)) { + + // Select random variable + InversionMethod field = new InversionMethod(dt.values); + int target = field.random(); + + // Get shortest path + return graph.getPathFrom(target); + } + } + + return null; + } + + private DoubleMatrix getProbabilityField( + DoubleMatrix fgDT, DoubleMatrix bgDT) { + + // Sum transforms + DoubleMatrix field = fgDT.clone(); + for (int i = 0; i < field.size; i++) { + field.values[i] += bgDT.values[i]; + } + + // Set probability of selected seeds to zero + for (Index2D seed : seeds) { + field.setDoubleAt(seed, 0.0); + } + + if (!isStoppingCriteriaSatisfied(field)) { + return field; + } + + return null; + } + + private static IntGraph buildGraph(ByteMatrix matrix) { + + final double SQRT_2 = Math.sqrt(2.0); + final byte[] values = matrix.values; + final int rows = matrix.rows; + final int cols = matrix.cols; + final IntGraph graph = new IntGraph(matrix.size); + + for (int i = 0; i < rows; i++) { + int k = i * cols; + + for (int j = 0; j < cols; j++, k++) { + if (values[k] != ERROR_VALUE) { + continue; + } + + // Locations neighboring pixels + final int north = k - cols; + final int south = k + cols; + final int west = k - 1; + final int east = k + 1; + final int northWest = north - 1; + final int northEast = north + 1; + final int southWest = south - 1; + final int southEast = south + 1; + + final boolean hasNorth = i > 0; + final boolean hasSouth = i + 1 < rows; + final boolean hasWest = j > 0; + final boolean hasEast = j + 1 < cols; + + if (hasNorth) { + if (hasWest && values[northWest] == ERROR_VALUE) { + graph.addDirectedEdge(k, northWest, SQRT_2); + } + + if (values[north] == ERROR_VALUE) { + graph.addDirectedEdge(k, north, 1.0); + } + + if (hasEast && values[northEast] == ERROR_VALUE) { + graph.addDirectedEdge(k, northEast, SQRT_2); + } + } + + if (hasWest && values[west] == ERROR_VALUE) { + graph.addDirectedEdge(k, west, 1.0); + } + + if (hasEast && values[east] == ERROR_VALUE) { + graph.addDirectedEdge(k, east, 1.0); + } + + if (hasSouth) { + if (hasWest && values[southWest] == ERROR_VALUE) { + graph.addDirectedEdge(k, southWest, SQRT_2); + } + + if (values[south] == ERROR_VALUE) { + graph.addDirectedEdge(k, south, 1.0); + } + + if (hasEast && values[southEast] == ERROR_VALUE) { + graph.addDirectedEdge(k, southEast, SQRT_2); + } + } + } + } + + return graph; + } + + private static DoubleMatrix distanceTransform(ByteMatrix error) { + DistanceTransform dt = new DistanceTransform(); + dt.init(error, Constants.ERROR_VALUE); + return dt.computeTransform(); + } + + private static boolean isStoppingCriteriaSatisfied(DoubleMatrix dt) { + return dt.maxValue() < 2.0; + } + + private static boolean nonzero(DoubleMatrix matrix) { + for (int i = 0; i < matrix.size; i++) { + if (matrix.values[i] != 0) { + return true; + } + } + return false; + } + + public static boolean isNonDeterministic() { + return true; + } +} diff --git a/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator3.class b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator3.class new file mode 100644 index 0000000..3120d9b Binary files /dev/null and b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator3.class differ diff --git a/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator3.java b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator3.java new file mode 100644 index 0000000..b1f8980 --- /dev/null +++ b/Annotation/src/ie/dcu/auto/automator/NonDeterministicAutomator3.java @@ -0,0 +1,312 @@ +package ie.dcu.auto.automator; + +import static ie.dcu.auto.Constants.ERROR_VALUE; +import ie.dcu.auto.*; +import ie.dcu.graph.dijkstra.IntGraph; +import ie.dcu.image.dt.DistanceTransform; +import ie.dcu.matrix.*; +import ie.dcu.segment.annotate.*; +import ie.dcu.stats.InversionMethod; + +import java.util.*; + +import org.eclipse.swt.graphics.Point; + +/** + * Implementation of the more complex non-deterministic strategy for interactive + * segmentation evaluation. This automator weights the pixels so that the paths + * found tend to stay closer to the center of the shape, rather than using the + * absolute shortest path + * + * @author Kevin McGuinness + * + */ +public class NonDeterministicAutomator3 + extends AbstractAutomator implements Automator +{ + private final Set seeds; + + public NonDeterministicAutomator3(AutomationData data) { + super(data); + this.seeds = new HashSet(); + } + + @Override + protected void doReset() { + seeds.clear(); + } + + @Override + protected void doStart() { + ByteMatrix fgError = getForegroundError(); + ByteMatrix bgError = getBackgroundError(); + + // Distance transform + DoubleMatrix fgDT = distanceTransform(fgError); + DoubleMatrix bgDT = distanceTransform(bgError); + + // Initialize foreground probability field + List fgPath = createPath(fgError, fgDT); + List bgPath = createPath(bgError, bgDT); + + // Add seeds + if (fgPath != null && bgPath != null) { + addSeedPath(fgDT, fgPath, AnnotationType.Foreground); + addSeedPath(bgDT, bgPath, AnnotationType.Background); + } else if (fgPath != null) { + addSeedPath(fgDT, fgPath, AnnotationType.Foreground); + } else if (bgPath != null) { + addSeedPath(bgDT, bgPath, AnnotationType.Background); + } else { + log("Automation complete"); + setDone(true); + } + } + + @Override + protected void doStep() { + ByteMatrix fgError = getForegroundError(); + ByteMatrix bgError = getBackgroundError(); + + DoubleMatrix fgDT = distanceTransform(fgError); + DoubleMatrix bgDT = distanceTransform(bgError); + + DoubleMatrix field = getProbabilityField(fgDT, bgDT); + + if (field != null) { + InversionMethod rv = new InversionMethod(field.values); + int seed = rv.random(); + List path = null; + AnnotationType type; + + if (fgError.values[seed] == ERROR_VALUE) { + type = AnnotationType.Foreground; + path = createPath(fgError, fgDT, seed); + + } else { + type = AnnotationType.Background; + path = createPath(bgError, bgDT, seed); + } + + if (path != null) { + addSeedPath(field, path, type); + } else { + addSeed(field, seed, type); + } + + } else { + log("Automation complete"); + setDone(true); + } + } + + private void addSeed(DoubleMatrix field, int seed, AnnotationType type) { + log("Adding single seed"); + + Index2D index = field.indexOf(seed); + double distance = field.doubleAt(seed); + int size = (int) Math.min(distance/2, MAX_BRUSH_SIZE); + size = Math.max(size, 1); + Point pt = getSwtPointForIndex(index); + getAnnotations().add(new Annotation(type, size, pt)); + seeds.add(index); + } + + private void addSeedPath( + DoubleMatrix field, List path, AnnotationType type) { + + log("Adding seed path"); + + int size = MAX_BRUSH_SIZE; + for (int k : path) { + double distance = field.doubleAt(k); + size = (int) Math.min(size, distance/2); + } + + size = Math.max(size, 1); + + for (int k : path) { + Index2D index = field.indexOf(k); + Point pt = getSwtPointForIndex(index); + getAnnotations().add(new Annotation(type, size, pt)); + seeds.add(index); + } + } + + private List createPath(ByteMatrix error, DoubleMatrix dt) { + if (nonzero(dt)) { + + // Select random variable + InversionMethod field = new InversionMethod(dt.values); + int source = field.random(); + + // Create path + return createPath(error, dt, source); + } + + return null; + } + + private List createPath(ByteMatrix error, DoubleMatrix dt, int source) { + + // Build graph + IntGraph graph = buildGraph(error, dt); + + // The graph may not contain the source pixel if it has no neighbors + if (graph.hasNode(source)) { + + // Ok, it does + graph.findPaths(source); + + // Mark inaccessible pixels with probability zero + for (int i = 0; i < dt.size; i++) { + if (!graph.hasNode(i)) { + dt.values[i] = 0.0; + } + } + + if (nonzero(dt)) { + + // Select random variable + InversionMethod field = new InversionMethod(dt.values); + int target = field.random(); + + // Get shortest path + return graph.getPathFrom(target); + } + } + + return null; + } + + private DoubleMatrix getProbabilityField( + DoubleMatrix fgDT, DoubleMatrix bgDT) { + + // Sum transforms + DoubleMatrix field = fgDT.clone(); + for (int i = 0; i < field.size; i++) { + field.values[i] += bgDT.values[i]; + } + + // Set probability of selected seeds to zero + for (Index2D seed : seeds) { + field.setDoubleAt(seed, 0.0); + } + + if (!isStoppingCriteriaSatisfied(field)) { + return field; + } + + return null; + } + + private static IntGraph buildGraph(ByteMatrix matrix, DoubleMatrix dt) { + + final double dtmax = dt.maxValue(); + final double SQRT_2 = Math.sqrt(2.0); + final byte[] values = matrix.values; + final int rows = matrix.rows; + final int cols = matrix.cols; + final IntGraph graph = new IntGraph(matrix.size); + + for (int i = 0; i < rows; i++) { + int k = i * cols; + + for (int j = 0; j < cols; j++, k++) { + if (values[k] != ERROR_VALUE) { + continue; + } + + // Locations neighboring pixels + final int north = k - cols; + final int south = k + cols; + final int west = k - 1; + final int east = k + 1; + final int northWest = north - 1; + final int northEast = north + 1; + final int southWest = south - 1; + final int southEast = south + 1; + + final boolean hasNorth = i > 0; + final boolean hasSouth = i + 1 < rows; + final boolean hasWest = j > 0; + final boolean hasEast = j + 1 < cols; + + double w; + + if (hasNorth) { + if (hasWest && values[northWest] == ERROR_VALUE) { + w = weight(dt.values[northWest], dtmax, SQRT_2); + graph.addDirectedEdge(k, northWest, w); + } + + if (values[north] == ERROR_VALUE) { + w = weight(dt.values[north], dtmax, 1); + graph.addDirectedEdge(k, north, w); + } + + if (hasEast && values[northEast] == ERROR_VALUE) { + w = weight(dt.values[northEast], dtmax, SQRT_2); + graph.addDirectedEdge(k, northEast, w); + } + } + + if (hasWest && values[west] == ERROR_VALUE) { + w = weight(dt.values[west], dtmax, 1); + graph.addDirectedEdge(k, west, w); + } + + if (hasEast && values[east] == ERROR_VALUE) { + w = weight(dt.values[east], dtmax, 1); + graph.addDirectedEdge(k, east, w); + } + + if (hasSouth) { + if (hasWest && values[southWest] == ERROR_VALUE) { + w = weight(dt.values[southWest], dtmax, SQRT_2); + graph.addDirectedEdge(k, southWest, w); + } + + if (values[south] == ERROR_VALUE) { + w = weight(dt.values[south], dtmax, 1); + graph.addDirectedEdge(k, south, w); + } + + if (hasEast && values[southEast] == ERROR_VALUE) { + w = weight(dt.values[southEast], dtmax, SQRT_2); + graph.addDirectedEdge(k, southEast, w); + } + } + } + } + + return graph; + } + + private static double weight(double n, double m, double d) { + return d*Math.exp(-n/m); + } + + private static DoubleMatrix distanceTransform(ByteMatrix error) { + DistanceTransform dt = new DistanceTransform(); + dt.init(error, Constants.ERROR_VALUE); + return dt.computeTransform(); + } + + private static boolean isStoppingCriteriaSatisfied(DoubleMatrix dt) { + return dt.maxValue() < 2.0; + } + + private static boolean nonzero(DoubleMatrix matrix) { + for (int i = 0; i < matrix.size; i++) { + if (matrix.values[i] != 0) { + return true; + } + } + return false; + } + + public static boolean isNonDeterministic() { + return true; + } +} diff --git a/Annotation/src/ie/dcu/eval/AbstractEvaluator.class b/Annotation/src/ie/dcu/eval/AbstractEvaluator.class new file mode 100644 index 0000000..91fb751 Binary files /dev/null and b/Annotation/src/ie/dcu/eval/AbstractEvaluator.class differ diff --git a/Annotation/src/ie/dcu/eval/AbstractEvaluator.java b/Annotation/src/ie/dcu/eval/AbstractEvaluator.java new file mode 100644 index 0000000..05ca3d7 --- /dev/null +++ b/Annotation/src/ie/dcu/eval/AbstractEvaluator.java @@ -0,0 +1,181 @@ +package ie.dcu.eval; + +import ie.dcu.matrix.ByteMatrix; + +import java.util.*; + +/** + * Abstract class to make implementing evaluators easier. Subclasses should set + * the values of name, description and vendor in the constructor, and add all + * the measures that will be computed. The subclasses implementation of the run + * method should call {@link #setResult(String, double)} for all the measures computed. + * + * @author Kevin McGuinness + */ +public abstract class AbstractEvaluator implements Evaluator { + + /** + * Map will contain the results of the evaluation. + */ + private final Map results; + + + /** + * Name of the evaluator, should be set by subclass on construction. + */ + protected String name; + + + /** + * Description of the evaluator, should be set by subclass on construction. + */ + protected String description; + + + /** + * Vendor of the evaluator, should be set by subclass on construction. + */ + protected String vendor; + + + /** + * Cached names of the measures; + */ + private transient String[] measures; + + + /** + * Constructor. + */ + public AbstractEvaluator() { + // Use a tree-map as we expect only a small number of measures + results = new TreeMap(); + } + + + /** + * Default implementation returns the name field. + */ + public String getName() { + return name; + } + + + /** + * Default implementation returns the description field. + */ + public String getDescription() { + return description; + } + + + /** + * Default implementation returns the vendor field. + */ + public String getVendor() { + return vendor; + } + + + + public String[] getMeasures() { + if (measures == null) { + Set keySet = results.keySet(); + measures = keySet.toArray(new String[keySet.size()]); + } + return measures; + } + + + public double getMeasure(String name) + throws IllegalStateException, IllegalArgumentException { + + Double measure = results.get(name); + + if (measure == null) { + + if (results.containsKey(name)) { + + // Measure not computed by run method + throw new IllegalStateException(); + } + + // Unknown measure name + throw new IllegalArgumentException(name + " is not a valid measure"); + } + + return measure; + } + + + /** + * Add a measure that the evaluator will compute. Subclasses should add all + * their measures using this method in their constructor. + * + * @param name + * The name of the measure. + */ + protected void addMeasure(String name) { + // Add measure with null value + results.put(name, null); + + // Invalidate cache + measures = null; + } + + + /** + * Set the value of a measure resulting from running the evaluator. This + * method should be called at the end of run to set the results of the + * evaluation. + * + * @param name + * The name of the measure. + * @param value + * The computed value. + * @throws IllegalArgumentException + * If the name of the measure has not been added with + * {@link #addMeasure(String)} + */ + protected void setResult(String name, double value) + throws IllegalArgumentException { + + // Ensure we're a real measure + if (!results.containsKey(name)) { + throw new IllegalArgumentException(); + } + + results.put(name, value); + } + + + /** + * Checks if the two masks are non-null and the have the same dimensions. If + * they do not, an IllegalArgumentException is thrown. Method is provided to + * let subclasses easily validate parameters to run(). + * + * @param a + * The first segmentation mask + * @param b + * The second segmentation mask + * @throws IllegalArgumentException + * If either mask is null or they have different + * dimensions. + */ + protected void check(ByteMatrix a, ByteMatrix b) + throws IllegalArgumentException + { + if (a == null) { + throw new IllegalArgumentException("null mask"); + } + + if (b == null) { + throw new IllegalArgumentException("null mask"); + } + + if (!a.sizeEquals(b)) { + throw new IllegalArgumentException("unequal dimensions"); + } + + } +} diff --git a/Annotation/src/ie/dcu/eval/BestEvaluator.class b/Annotation/src/ie/dcu/eval/BestEvaluator.class new file mode 100644 index 0000000..6eeb15b Binary files /dev/null and b/Annotation/src/ie/dcu/eval/BestEvaluator.class differ diff --git a/Annotation/src/ie/dcu/eval/BestEvaluator.java b/Annotation/src/ie/dcu/eval/BestEvaluator.java new file mode 100644 index 0000000..e8995a4 --- /dev/null +++ b/Annotation/src/ie/dcu/eval/BestEvaluator.java @@ -0,0 +1,84 @@ +package ie.dcu.eval; + +import ie.dcu.matrix.ByteMatrix; + +/** + * Extracts the most useful measures from the other two evaluators + * + * @author Kevin McGuinness + */ +public class BestEvaluator extends AbstractEvaluator { + + /** + * Object Jaccard index. + */ + public static final String OBJECT_ACCURACY = "Object"; + + /** + * Fuzzy boundary accuracy measure. + */ + public static final String BOUNDARY_ACCURACY = "Boundary"; + + /** + * Measures computed by the confusion matrix evaluator + */ + private final ConfusionMatrixEvaluator cmEvaluator; + + /** + * Measures computed by the boundary accuracy evaluator + */ + private final BoundaryAccuracyEvaluator baEvaluator; + + /** + * Constructor. + */ + public BestEvaluator() { + + // Create evaluators + cmEvaluator = new ConfusionMatrixEvaluator(); + baEvaluator = new BoundaryAccuracyEvaluator(); + + // Setup evaluator + name = "Boundary and Object Accuracy Evaluator"; + description = "Computes object jaccard index and fuzzy boundary index"; + vendor = "Kevin McGuinness"; + + // Add measures + addMeasure(OBJECT_ACCURACY); + addMeasure(BOUNDARY_ACCURACY); + } + + /** + * Set the sigma parameter. + * + * The sigma parameter controls the tolerance of the fuzzy Jaccard + * measure. + * + * @param sigma A value greater than zero. + */ + public void setSigma(double sigma) { + baEvaluator.setSigma(sigma); + } + + /** + * Get the sigma parameter. + */ + public double getSigma() { + return baEvaluator.getSigma(); + } + + /** + * Run the evaluator. + */ + public void run(ByteMatrix mask, ByteMatrix gt) + throws IllegalArgumentException + { + cmEvaluator.run(mask, gt); + baEvaluator.run(mask, gt); + + setResult(OBJECT_ACCURACY, cmEvaluator.getMeasure( + ConfusionMatrixEvaluator.JACCARD)); + setResult(BOUNDARY_ACCURACY, baEvaluator.getMeasure( + BoundaryAccuracyEvaluator.FUZZY_ACCURACY)); + } +} diff --git a/Annotation/src/ie/dcu/eval/BinaryClassifierEvaluation.class b/Annotation/src/ie/dcu/eval/BinaryClassifierEvaluation.class new file mode 100644 index 0000000..27f9238 Binary files /dev/null and b/Annotation/src/ie/dcu/eval/BinaryClassifierEvaluation.class differ diff --git a/Annotation/src/ie/dcu/eval/BinaryClassifierEvaluation.java b/Annotation/src/ie/dcu/eval/BinaryClassifierEvaluation.java new file mode 100644 index 0000000..1425436 --- /dev/null +++ b/Annotation/src/ie/dcu/eval/BinaryClassifierEvaluation.java @@ -0,0 +1,216 @@ +package ie.dcu.eval; + +import static java.lang.Math.sqrt; + + +/** + * Computes a variety of statistical measures and indices to evaluate binary + * classifiers based on a confusion matrix computed against a reference. + * + * @author Kevin McGuinness + */ +public class BinaryClassifierEvaluation { + public final double tp; + public final double fp; + public final double tn; + public final double fn; + public final double total; + + + public BinaryClassifierEvaluation(int[][] c) { + this(c[0][0], c[0][1], c[1][0], c[1][1]); + } + + + public BinaryClassifierEvaluation(long[][] c) { + this(c[0][0], c[0][1], c[1][0], c[1][1]); + } + + + public BinaryClassifierEvaluation(long tp, long fn, long fp, long tn) { + check(this.tp = tp); + check(this.fp = fp); + check(this.tn = tn); + check(this.fn = fn); + this.total = tp + fp + tn + fn; + } + + + public final double getTotal() { + return total; + } + + + public final double getPositiveReference() { + return tp + fn; + } + + + public final double getNegativeReference() { + return tn + fp; + } + + + public final double getPositiveResponse() { + return tp + fp; + } + + + public final double getNegativeResponse() { + return tn + fn; + } + + + public final double getCorrectResponse() { + return tp + tn; + } + + + public final double getIncorrectResponse() { + return fp + fn; + } + + + public final double getReferenceLikelihood() { + return (tp + fn) / total; + } + + + public final double getResponseLikelihood() { + return (tp + fp) / total; + } + + + public final double getAccuracy() { + return (tp + tn) / total; + } + + + public final double getRecall() { + return tp / (tp + fn); + } + + public final double getPrecision() { + return tp / (tp + fp); + } + + + public final double getRejectionRecall() { + return tn / (tn + fp); + } + + + public final double getRejectionPrecision() { + return tn / (tn + fn); + } + + + public final double getFMeasure() { + return getFMeasure(1.0); + } + + + public final double getFMeasure(double beta) { + double b = beta * beta, p = getPrecision(), r = getRecall(); + return (1.0 + b) * p * r / (r + (b * p)); + } + + + public final double getRandIndex() { + // Same as accuracy in the binary case + return getAccuracy(); + } + + + public final double getJaccardIndex() { + // Jaccard similarity coefficient J + return tp / (tp + fn + fp); + } + + + public final double getJaccardDistance() { + // Jaccard distance J' + return (fp + fn) / (fp + fn + tp); + } + + + public final double getFowlkesMallowsIndex() { + // Fowlkes-Mallows 83 - A method for comparing 2 hierarchical clusterings + double tk = sq(tp) + sq(fn) + sq(fp) + sq(tn) - total; + double pk = sq(tp + fp) + sq(fn + tn) - total; + double qk = sq(tp + fn) + sq(fp + tn) - total; + return tk / sqrt(pk*qk); + } + + + public final double getChiSquared() { + double d = tp * tn - fp * fn; + return total * d * d / ((tp + fn) * (fp + tn) * (tp + fp) * (fn + tn)); + } + + + public final double getPhiSquared() { + return getChiSquared() / total; + } + + + public final double getYulesQ() { + return (tp * tn - fp * fn) / (tp * tn + fp * fn); + } + + + public final double getYulesY() { + return (sqrt(tp * tn) - sqrt(fp * fn)) / (sqrt(tp * tn) + sqrt(fp * fn)); + } + + + public final double getAccuracyDeviation() { + double a = getAccuracy(); + return sqrt(a * (1.0 - a) / total); + } + + + public final double getRandomAccuracy() { + double ref = (tp + fn) / total; + double res = (tp + fp) / total; + return ref * res + (1.0 - ref) * (1.0 - res); + } + + + public final double getRandomAccuracyUnbiased() { + double avg = tp / total + (fn + fp) / (2.0 * total); + return avg * avg + (1.0 - avg) * (1.0 - avg); + } + + + public final double getKappa() { + return kappa(getAccuracy(), getRandomAccuracy()); + } + + + public final double getKappaUnbiased() { + return kappa(getAccuracy(), getRandomAccuracyUnbiased()); + } + + + public final double getKappaNoPrevalence() { + return 2.0 * getAccuracy() - 1.0; + } + + + private static double kappa(double observed, double expected) { + return (observed - expected) / (1 - expected); + } + + + private static double sq(double x) { + return x*x; + } + + + private static void check(double v) { + if (v < 0) { + throw new IllegalArgumentException(); + } + } +} \ No newline at end of file diff --git a/Annotation/src/ie/dcu/eval/BoundaryAccuracyEvaluator.class b/Annotation/src/ie/dcu/eval/BoundaryAccuracyEvaluator.class new file mode 100644 index 0000000..d5cd2f4 Binary files /dev/null and b/Annotation/src/ie/dcu/eval/BoundaryAccuracyEvaluator.class differ diff --git a/Annotation/src/ie/dcu/eval/BoundaryAccuracyEvaluator.java b/Annotation/src/ie/dcu/eval/BoundaryAccuracyEvaluator.java new file mode 100644 index 0000000..518b086 --- /dev/null +++ b/Annotation/src/ie/dcu/eval/BoundaryAccuracyEvaluator.java @@ -0,0 +1,237 @@ +package ie.dcu.eval; + +import ie.dcu.image.dt.DistanceTransform; +import ie.dcu.matrix.*; + +/** + * An evaluator that computes internal object boundary accuracy using + * the Jaccard and the fuzzy Jaccard indices. + * + * @author Kevin McGuinness + */ +public class BoundaryAccuracyEvaluator extends AbstractEvaluator { + + /** + * Name of the fuzzy accuracy measure. + */ + public static final String FUZZY_ACCURACY = "FBA"; + + /** + * Name of the binary accuracy measure. + */ + public static final String BINARY_ACCURACY = "BBA"; + + /** + * Default value of the sigma parameter. + */ + public static final double DEFAULT_SIGMA = 3.5; + + /** + * Sigma parameter. + */ + private double sigma; + + /** + * Constructor + */ + public BoundaryAccuracyEvaluator() { + + // Setup evaluator + name = "Boundary Accuracy Evaluator"; + description = "Compute internal object boundary accuracy " + + "using the Jaccard and the fuzzy Jaccard measures"; + vendor = "Kevin McGuinness"; + + // Add measures + addMeasure(FUZZY_ACCURACY); + addMeasure(BINARY_ACCURACY); + + // Set default sigma value + sigma = DEFAULT_SIGMA; + } + + /** + * Get the sigma parameter. + */ + public double getSigma() { + return sigma; + } + + /** + * Set the sigma parameter. + * + * The sigma parameter controls the tolerance of the fuzzy Jaccard + * measure. + * + * @param sigma A value greater than zero. + */ + public void setSigma(double sigma) { + if (sigma <= 0) { + throw new IllegalArgumentException("sigma must be > 0"); + } + this.sigma = sigma; + } + + /** + * Run evaluator. + */ + public void run(ByteMatrix a, ByteMatrix b) + throws IllegalArgumentException + { + // Check arguments + check(a, b); + + // Find boundaries + ByteMatrix boundaryA = findInternalBoundary(a); + ByteMatrix boundaryB = findInternalBoundary(b); + + // Compute accuracy + double fba = fuzzyBoundaryAccuracy(boundaryA, boundaryB); + double bba = binaryBoundaryAccuracy(boundaryA, boundaryB); + + // Set result + setResult(FUZZY_ACCURACY, fba); + setResult(BINARY_ACCURACY, bba); + } + + /** + * Compute fuzzy boundary accuracy between given boundary masks. + */ + private double fuzzyBoundaryAccuracy( + ByteMatrix boundaryA, ByteMatrix boundaryB) + { + // Compute distance transforms + double[] dtA = distanceTransform(boundaryA).values; + double[] dtB = distanceTransform(boundaryB).values; + + // Compute Gaussian + applyGaussian(dtA); + applyGaussian(dtB); + + // Compute fuzzy Jaccard + return fuzzyJaccard(dtA, dtB); + } + + /** + * Compute binary boundary accuracy between given boundary masks. + */ + private double binaryBoundaryAccuracy( + ByteMatrix boundaryA, ByteMatrix boundaryB) + { + // Operate directly on the masks + return binaryJaccard(boundaryA.values, boundaryB.values); + } + + /** + * Fuzzy jaccard computation on fuzzy masks + */ + private double fuzzyJaccard(double[] a, double[] b) { + assert (a.length == b.length); + + double num = 0; + double den = 0; + + for (int i = 0; i < a.length; i++) { + num += Math.min(a[i], b[i]); + den += Math.max(a[i], b[i]); + } + + if (den != 0.0) { + num /= den; + return num; + } + + return 0.0; + } + + /** + * Binary Jaccard computation on binary masks. + */ + private double binaryJaccard(byte[] a, byte[] b) { + assert (a.length == b.length); + + double union_v = 0; + double intersection = 0; + + for (int i = 0; i < a.length; i++) { + if (a[i] == FG || b[i] == FG) { + union_v++; + } + if (a[i] == FG && b[i] == FG) { + intersection++; + } + } + + if (union_v != 0) { + return intersection / union_v; + } + + return 0; + } + + /** + * Apply gaussian kernel to mask. + */ + private void applyGaussian(double[] values) { + double denominator = 2.0 * sigma * sigma; + for (int i = 0; i < values.length; i++) { + double x = values[i]; + values[i] = Math.exp(-(x*x) / denominator); + } + } + + /** + * Compute Euclidean distance transform of mask. + */ + private DoubleMatrix distanceTransform(ByteMatrix m) { + DistanceTransform dt = new DistanceTransform(); + dt.init(m, BG); + return dt.computeTransform(); + } + + /** + * Determine the internal boundary of the foreground object. + */ + private static ByteMatrix findInternalBoundary(ByteMatrix m) { + + ByteMatrix result = new ByteMatrix(m.rows, m.cols); + + for (int i = 0; i < m.rows; i++) { + int k = i * m.cols; + + for (int j = 0; j < m.cols; j++, k++) { + if (m.values[k] == FG) { + + // border pixels + if (i == 0 || j == 0 || + i == m.rows - 1 || j == m.cols - 1) + { + result.values[k] = FG; + continue; + } + + // pixels with neighbors in background + + if (m.values[k-m.cols-1] == BG || // (i-1, j-1) + m.values[k-m.cols] == BG || // (i , j-1) + m.values[k-m.cols+1] == BG || // (i+1, j-1) + m.values[k-1] == BG || // (i-1, j ) + m.values[k+1] == BG || // (i+1, j ) + m.values[k+m.cols-1] == BG || // (i-1, j+1) + m.values[k+m.cols] == BG || // (i , j+1) + m.values[k+m.cols+1] == BG) // (i+1, j+1) + { + result.values[k] = FG; + } else { + result.values[k] = BG; + } + } else { + result.values[k] = BG; + } + } + } + + return result; + } + +} diff --git a/Annotation/src/ie/dcu/eval/ConfusionMatrixEvaluator.class b/Annotation/src/ie/dcu/eval/ConfusionMatrixEvaluator.class new file mode 100644 index 0000000..5a208af Binary files /dev/null and b/Annotation/src/ie/dcu/eval/ConfusionMatrixEvaluator.class differ diff --git a/Annotation/src/ie/dcu/eval/ConfusionMatrixEvaluator.java b/Annotation/src/ie/dcu/eval/ConfusionMatrixEvaluator.java new file mode 100644 index 0000000..4323679 --- /dev/null +++ b/Annotation/src/ie/dcu/eval/ConfusionMatrixEvaluator.java @@ -0,0 +1,72 @@ +/** + * + */ +package ie.dcu.eval; + +import ie.dcu.matrix.ByteMatrix; + +/** + * An evaluator that computes several standard statistical measure using a + * confusion matrix. + * + * @author Kevin McGuinness + */ +public class ConfusionMatrixEvaluator extends AbstractEvaluator { + public static final String ACCURACY = "Accuracy"; + public static final String PRECISION = "Precision"; + public static final String RECALL = "Recall"; + public static final String F_MEASURE = "F-Measure"; + public static final String JACCARD = "Jaccard"; + + public ConfusionMatrixEvaluator() { + name = "Confusion Matrix Evaluator"; + description = "Computes standard measures using a confusion matrix"; + vendor = "Kevin McGuinness"; + + // Add measures + addMeasure(ACCURACY); + addMeasure(PRECISION); + addMeasure(RECALL); + addMeasure(F_MEASURE); + addMeasure(JACCARD); + } + + + public void run(ByteMatrix a, ByteMatrix b) { + + // Check preconditions + check(a, b); + + // Confusion matrix (confused? :-P) + int[][] c = new int[2][2]; + + // Zero matrix + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + c[i][j] = 0; + } + } + + // Compute confusion + for (int i = 0; i < a.size; i++) { + + // Indices into confusion matrix + int idx1 = a.values[i] == FG ? 0 : 1; + int idx2 = b.values[i] == FG ? 0 : 1; + + // Increment confusion + c[idx1][idx2]++; + } + + // Compute measures and set results + BinaryClassifierEvaluation ev = + new BinaryClassifierEvaluation(c); + + // Set results + setResult(ACCURACY, ev.getAccuracy()); + setResult(PRECISION, ev.getPrecision()); + setResult(RECALL, ev.getRecall()); + setResult(F_MEASURE, ev.getFMeasure()); + setResult(JACCARD, ev.getJaccardIndex()); + } +} diff --git a/Annotation/src/ie/dcu/eval/Evaluator.class b/Annotation/src/ie/dcu/eval/Evaluator.class new file mode 100644 index 0000000..3c463c6 Binary files /dev/null and b/Annotation/src/ie/dcu/eval/Evaluator.class differ diff --git a/Annotation/src/ie/dcu/eval/Evaluator.java b/Annotation/src/ie/dcu/eval/Evaluator.java new file mode 100644 index 0000000..ee21e1f --- /dev/null +++ b/Annotation/src/ie/dcu/eval/Evaluator.java @@ -0,0 +1,90 @@ +/** + * + */ +package ie.dcu.eval; + +import ie.dcu.matrix.ByteMatrix; +import ie.dcu.segment.SegmentationMask; + +/** + * Interface for a class that is capable of evaluating a segmentation mask + * against a ground truth. + * + * @author Kevin McGuinness + */ +public interface Evaluator { + + /** + * Value for the foreground pixels. + */ + public static final byte FG = SegmentationMask.FOREGROUND; + + /** + * Value for the background pixels. + */ + public static final byte BG = SegmentationMask.BACKGROUND; + + /** + * Returns the name of the evaluator. + * + * @return The evaluator name. (never null). + */ + public String getName(); + + + /** + * Returns a short description of the evaluator. + * + * @return A description (never null). + */ + public String getDescription(); + + + /** + * Returns the name of the author or vendor. + * + * @return The vendor. + */ + public String getVendor(); + + + /** + * Run the evaluator on the given mask and ground truth. + * + * @param mask + * The segmentation mask to evaluate. + * @param gt + * The ground truth to evaluate against. + * @throws IllegalArgumentException + * If the mask or ground truth are null, if they do + * not have the same dimensions, or if they contain invalid pixel + * values. + * + */ + public void run(ByteMatrix mask, ByteMatrix gt) + throws IllegalArgumentException; + + + /** + * Returns the names of the measures generated by this evaluator. + * + * @return The names of the generated measures. + */ + public String[] getMeasures(); + + + /** + * Get the computed value of the measure with the given name. + * + * @param name + * The measure name. + * @return The value of the computed measure. + * + * @throws IllegalStateException + * If the run method was not previously called successfully. + * @throws IllegalArgumentException + * If the name is not in the array returned by {@link #getMeasures()}. + */ + public double getMeasure(String name) + throws IllegalStateException, IllegalArgumentException; +} diff --git a/Annotation/src/ie/dcu/graph/dijkstra/Graph$Edge.class b/Annotation/src/ie/dcu/graph/dijkstra/Graph$Edge.class new file mode 100644 index 0000000..4ef1f62 Binary files /dev/null and b/Annotation/src/ie/dcu/graph/dijkstra/Graph$Edge.class differ diff --git a/Annotation/src/ie/dcu/graph/dijkstra/Graph$Node.class b/Annotation/src/ie/dcu/graph/dijkstra/Graph$Node.class new file mode 100644 index 0000000..1f75ffa Binary files /dev/null and b/Annotation/src/ie/dcu/graph/dijkstra/Graph$Node.class differ diff --git a/Annotation/src/ie/dcu/graph/dijkstra/Graph.class b/Annotation/src/ie/dcu/graph/dijkstra/Graph.class new file mode 100644 index 0000000..4729f55 Binary files /dev/null and b/Annotation/src/ie/dcu/graph/dijkstra/Graph.class differ diff --git a/Annotation/src/ie/dcu/graph/dijkstra/Graph.java b/Annotation/src/ie/dcu/graph/dijkstra/Graph.java new file mode 100644 index 0000000..42d4c6a --- /dev/null +++ b/Annotation/src/ie/dcu/graph/dijkstra/Graph.java @@ -0,0 +1,377 @@ +package ie.dcu.graph.dijkstra; + +import java.util.*; + +/** + * Implementation of Dijkstra's shortest path algorithm. + * + * @author Kevin McGuinness + * + * @param + * The node type for the graph. + */ +public class Graph { + + /** + * Map of nodes to node objects. + */ + private final Map> nodes; + + /** + * The source node from which all paths are found. + */ + private T source; + + /** + * Flag to indicate whether or not the algorithm has been run. + */ + private boolean done; + + /** + * Construct empty graph. + */ + public Graph() { + nodes = new HashMap>(); + done = false; + } + + /** + * Construct empty graph with the given initial capacity of nodes. + */ + public Graph(int initialCapacity) { + nodes = new HashMap>(initialCapacity); + done = false; + } + + /** + * Add a directed edge between the given source and target objects. + */ + public void addDirectedEdge(T source, T target, double weight) { + checkWeight(weight); + + // Get source node + Node srcNode = nodes.get(source); + if (srcNode == null) { + srcNode = new Node(source); + nodes.put(source, srcNode); + } + + // Get target node + Node dstNode = nodes.get(target); + if (dstNode == null) { + dstNode = new Node(target); + nodes.put(target, dstNode); + } + + // Add edge + srcNode.addDirectedEdge(dstNode, weight); + done = false; + } + + /** + * Add an undirected edge between the given nodes + */ + public void addUndirectedEdge(T node1, T node2, double weight) { + checkWeight(weight); + + // Get source node + Node srcNode = nodes.get(node1); + if (srcNode == null) { + srcNode = new Node(node1); + nodes.put(node1, srcNode); + } + + // Get target node + Node dstNode = nodes.get(node2); + if (dstNode == null) { + dstNode = new Node(node2); + nodes.put(node2, dstNode); + } + + // Add edge + srcNode.addDirectedEdge(dstNode, weight); + dstNode.addDirectedEdge(srcNode, weight); + done = false; + } + + /** + * Returns the (unmodifiable) set of nodes in the graph. + */ + public Set nodes() { + return Collections.unmodifiableSet(nodes.keySet()); + } + + /** + * Returns true if the given object is a node in the graph. + */ + public boolean hasNode(T node) { + return nodes.containsKey(node); + } + + /** + * Returns the edge weight for the directed edge between src and dst, or + * positive infinity if there is no such edge. + */ + public double getEdgeWeight(T src, T dst) { + Node n1 = nodes.get(src); + if (n1 != null) { + for (Edge edge : n1.edges) { + if (edge.target.equals(dst)) { + return edge.weight; + } + } + } + return Double.POSITIVE_INFINITY; + } + + /** + * Run Dijkstra's method for the given source node. + */ + public void findPaths(T source) { + + if (!hasNode(source)) { + throw new IllegalArgumentException("src node not in graph"); + } + + // Check if we are re-running for a new source node + if (this.source != source) { + this.source = source; + this.done = false; + } + + if (!done) { + + // Initialize nodes + for (Node node : nodes.values()) { + node.visited = false; + node.distance = Double.POSITIVE_INFINITY; + node.previous = null; + } + + // Create node queue + PriorityQueue> queue = + new PriorityQueue>(); + + // Set distance to zero and add first node to the queue + Node node = nodes.get(source); + node.distance = 0.0; + queue.add(node); + + // Run Dijkstra's method + while (!queue.isEmpty()) { + node = queue.remove(); + + if (node.visited) { + continue; + } + + node.visited = true; + + for (Edge edge : node.edges) { + Node target = edge.target; + + double distance = node.distance + edge.weight; + if (distance < target.distance) { + target.previous = node; + target.distance = distance; + } + + if (!target.visited) { + queue.add(target); + } + } + } + + // Done + done = true; + } + } + + /** + * Returns the source node or null if the {@link #findPaths(Object)} + * method has not yet been called. + */ + public T getSource() { + return source; + } + + /** + * Returns the shortest path from the source to the object. + * + * @throws IllegalStateException + * if the {@link #findPaths(Object)} function has not been called. + */ + public List getPathTo(T object) { + List path = getPathFrom(object); + Collections.reverse(path); + return path; + } + + /** + * Returns the shortest path from the object to the source. + * + * @throws IllegalStateException + * if the {@link #findPaths(Object)} function has not been called. + */ + public List getPathFrom(T object) { + ensureDone(); + Node node = nodes.get(object); + List list = new LinkedList(); + while (node != null) { + list.add(node.object); + node = node.previous; + } + return list; + } + + /** + * Get the distance to the object. Returns infinity if the object is + * not in the graph. + */ + public double getDistanceTo(T object) { + ensureDone(); + Node node = nodes.get(object); + return node != null ? node.distance : Double.POSITIVE_INFINITY; + } + + /** + * Get the distance from the source node to the farthest node in graph. + * Returns zero if there are no nodes. + */ + public double getDistanceOfLongestPath() { + double max = 0.0; + for (Node n : nodes.values()) { + if (n.distance > max) { + max = n.distance; + } + } + return max; + } + + /** + * Returns the node that is farthest away from the source node. + * + * @throws IllegalStateException + * if the {@link #findPaths(Object)} function has not been called. + */ + public T getFarthestNode() { + ensureDone(); + + T node = null; + double max = 0.0; + for (Node n : nodes.values()) { + if (n.distance > max) { + max = n.distance; + node = n.object; + } + } + + return node; + } + + /** + * Throws an exception if the done flag is not set. + */ + private final void ensureDone() { + if (!done) { + throw new IllegalStateException("findPaths never called"); + } + } + + /** + * Check the specified edge weight is valid. + */ + private static void checkWeight(double weight) { + if (weight < 0) { + throw new IllegalArgumentException("negative weights not allowed"); + } + + if (weight == Double.POSITIVE_INFINITY) { + throw new IllegalArgumentException("infinite weights not allowed"); + } + } + + /** + * Graph node containing an object of type T. + */ + private static class Node implements Comparable> { + + /** + * The object the node contains. + */ + public final T object; + + /** + * List of edges to adjacent nodes. + */ + public final List> edges; + + /** + * Flag to indicate the node has been visited (dijkstras algorithm). + */ + public boolean visited; + + /** + * The minimum distance so far to this node (dijkstras algorithm) + */ + public double distance; + + /** + * The previous node in the shortest path. + */ + public Node previous; + + /** + * Construct the node for an object. + * + * @param object An object (non-null) + */ + public Node(T object) { + assert (object != null); + this.object = object; + this.edges = new ArrayList>(8); + this.visited = false; + this.distance = Double.POSITIVE_INFINITY; + this.previous = null; + } + + /** + * Add a directed edge between this node and an adjacent one. + */ + public final void addDirectedEdge(Node target, double weight) { + edges.add(new Edge(target, weight)); + } + + /** + * Nodes are sorted based on distance. + */ + public int compareTo(Node n) { + return distance < n.distance ? -1 : (distance == n.distance ? 0 : 1); + } + } + + /** + * A weighted directed edge. + */ + private static class Edge { + + /** + * Target node + */ + public final Node target; + + /** + * Edge weight + */ + public final double weight; + + /** + * Edge constructor + */ + public Edge(Node target, double weight) { + assert (target != null); + this.target = target; + this.weight = weight; + } + } +} diff --git a/Annotation/src/ie/dcu/graph/dijkstra/IntGraph$Edge.class b/Annotation/src/ie/dcu/graph/dijkstra/IntGraph$Edge.class new file mode 100644 index 0000000..5b2e720 Binary files /dev/null and b/Annotation/src/ie/dcu/graph/dijkstra/IntGraph$Edge.class differ diff --git a/Annotation/src/ie/dcu/graph/dijkstra/IntGraph$Node.class b/Annotation/src/ie/dcu/graph/dijkstra/IntGraph$Node.class new file mode 100644 index 0000000..435b7bd Binary files /dev/null and b/Annotation/src/ie/dcu/graph/dijkstra/IntGraph$Node.class differ diff --git a/Annotation/src/ie/dcu/graph/dijkstra/IntGraph.class b/Annotation/src/ie/dcu/graph/dijkstra/IntGraph.class new file mode 100644 index 0000000..ed47c00 Binary files /dev/null and b/Annotation/src/ie/dcu/graph/dijkstra/IntGraph.class differ diff --git a/Annotation/src/ie/dcu/graph/dijkstra/IntGraph.java b/Annotation/src/ie/dcu/graph/dijkstra/IntGraph.java new file mode 100644 index 0000000..fd18174 --- /dev/null +++ b/Annotation/src/ie/dcu/graph/dijkstra/IntGraph.java @@ -0,0 +1,397 @@ +package ie.dcu.graph.dijkstra; + +import java.util.*; + +/** + * Implementation of Dijkstra's shortest path algorithm, optimized + * for nodes that have integer indices in a fixed integer range. + * + * @author Kevin McGuinness + */ +public class IntGraph { + + /** + * Map of node indices to node objects. + */ + private final Node[] nodes; + + /** + * The source node from which all paths are found. + */ + private int source; + + /** + * Flag to indicate whether or not the algorithm has been run. + */ + private boolean done; + + /** + * Number of nodes inserted into the graph. + */ + private int nodeCount; + + /** + * Construct empty graph which can hold nodes up to the given node index. + */ + public IntGraph(int maxNodeIndex) { + nodes = new Node[maxNodeIndex]; + nodeCount = 0; + done = false; + } + + /** + * Reset (clear) the graph. + */ + public void clear() { + Arrays.fill(nodes, null); + nodeCount = 0; + done = false; + } + + /** + * Add a directed edge between the given source and target objects. + */ + public void addDirectedEdge(int source, int target, double weight) { + checkWeight(weight); + + // Get source node + Node srcNode = nodes[source]; + if (srcNode == null) { + srcNode = nodes[source] = new Node(source); + nodeCount++; + } + + // Get target node + Node dstNode = nodes[target]; + if (dstNode == null) { + dstNode = nodes[target] = new Node(target); + nodeCount++; + } + + // Add edge + srcNode.addDirectedEdge(dstNode, weight); + done = false; + } + + /** + * Add an undirected edge between the given nodes + */ + public void addUndirectedEdge(int node1, int node2, double weight) { + checkWeight(weight); + + // Get source node + Node srcNode = nodes[node1]; + if (srcNode == null) { + srcNode = nodes[node1] = new Node(node1); + nodeCount++; + } + + // Get target node + Node dstNode = nodes[node2]; + if (dstNode == null) { + dstNode = nodes[node2] = new Node(node2); + nodeCount++; + } + + // Add edge + srcNode.addDirectedEdge(dstNode, weight); + dstNode.addDirectedEdge(srcNode, weight); + done = false; + } + + /** + * Returns the set of nodes in the graph. + */ + public Set nodes() { + Set nodeSet = new HashSet(); + for (int i = 0; i < nodes.length; i++) { + if (nodes[i] != null) { + nodeSet.add(i); + } + } + return nodeSet; + } + + /** + * Returns true if the given object is a node in the graph. + */ + public boolean hasNode(int node) { + return nodes[node] != null; + } + + /** + * Returns the edge weight for the directed edge between src and dst, or + * positive infinity if there is no such edge. + */ + public double getEdgeWeight(int src, int dst) { + Node n1 = nodes[src]; + if (n1 != null) { + for (Edge edge : n1.edges) { + if (edge.target.equals(dst)) { + return edge.weight; + } + } + } + return Double.POSITIVE_INFINITY; + } + + /** + * Run Dijkstra's method for the given source node. + */ + public void findPaths(int source) { + + if (!hasNode(source)) { + throw new IllegalArgumentException("src node not in graph: " + source); + } + + // Check if we are re-running for a new source node + if (this.source != source) { + this.source = source; + this.done = false; + } + + if (!done) { + + // Initialize nodes + for (Node node : nodes) { + if (node != null) { + node.visited = false; + node.distance = Double.POSITIVE_INFINITY; + node.previous = null; + } + } + + // Create node queue + PriorityQueue queue = + new PriorityQueue(); + + // Set distance to zero and add first node to the queue + Node node = nodes[source]; + node.distance = 0.0; + queue.add(node); + + // Run Dijkstra's method + while (!queue.isEmpty()) { + node = queue.remove(); + + if (node.visited) { + continue; + } + + node.visited = true; + + for (Edge edge : node.edges) { + Node target = edge.target; + + if (target.visited) { + continue; + } + + double distance = node.distance + edge.weight; + if (distance < target.distance) { + target.previous = node; + target.distance = distance; + } + + queue.add(target); + } + } + + done = true; + } + } + + /** + * Returns the number of nodes in the graph. + */ + public int getNodeCount() { + return nodeCount; + } + + /** + * Returns the source node or null if the {@link #findPaths(int)} + * method has not yet been called. + */ + public int getSource() { + return source; + } + + /** + * Returns the shortest path from the source to the object. + * + * @throws IllegalStateException + * if the {@link #findPaths(int)} function has not been called. + */ + public List getPathTo(int object) { + List path = getPathFrom(object); + Collections.reverse(path); + return path; + } + + /** + * Returns the shortest path from the object to the source. + * + * @throws IllegalStateException + * if the {@link #findPaths(int)} function has not been called. + */ + public List getPathFrom(int object) { + ensureDone(); + Node node = nodes[object]; + List list = new LinkedList(); + while (node != null) { + list.add(node.object); + node = node.previous; + } + return list; + } + + /** + * Get the distance to the object. Returns infinity if the object is + * not in the graph. + */ + public double getDistanceTo(int object) { + ensureDone(); + Node node = nodes[object]; + return node != null ? node.distance : Double.POSITIVE_INFINITY; + } + + /** + * Get the distance from the source node to the farthest node in graph. + * Returns zero if there are no nodes. + */ + public double getDistanceOfLongestPath() { + double max = 0.0; + for (Node n : nodes) { + if (n != null && n.distance > max) { + max = n.distance; + } + } + return max; + } + + /** + * Returns the node that is farthest away from the source node. + * + * @throws IllegalStateException + * if the {@link #findPaths(int)} function has not been called. + */ + public int getFarthestNode() { + ensureDone(); + + int node = -1; + double max = 0.0; + for (Node n : nodes) { + if (n != null && n.distance > max) { + max = n.distance; + node = n.object; + } + } + + return node; + } + + /** + * Throws an exception if the done flag is not set. + */ + private final void ensureDone() { + if (!done) { + throw new IllegalStateException("findPaths never called"); + } + } + + /** + * Check the specified edge weight is valid. + */ + private static void checkWeight(double weight) { + if (weight < 0) { + throw new IllegalArgumentException("negative weights not allowed"); + } + + if (weight == Double.POSITIVE_INFINITY) { + throw new IllegalArgumentException("infinite weights not allowed"); + } + } + + /** + * Graph node containing an object of type T. + */ + private static class Node implements Comparable { + + /** + * The object the node contains. + */ + public final int object; + + /** + * List of edges to adjacent nodes. + */ + public final List edges; + + /** + * Flag to indicate the node has been visited (dijkstras algorithm). + */ + public boolean visited; + + /** + * The minimum distance so far to this node (dijkstras algorithm) + */ + public double distance; + + /** + * The previous node in the shortest path. + */ + public Node previous; + + /** + * Construct the node for an object. + * + * @param object An object (non-null) + */ + public Node(int object) { + this.object = object; + this.edges = new ArrayList(8); + this.visited = false; + this.distance = Double.POSITIVE_INFINITY; + this.previous = null; + } + + /** + * Add a directed edge between this node and an adjacent one. + */ + public final void addDirectedEdge(Node target, double weight) { + edges.add(new Edge(target, weight)); + } + + /** + * Nodes are sorted based on distance. + */ + public int compareTo(Node n) { + return distance < n.distance ? -1 : (distance == n.distance ? 0 : 1); + } + } + + /** + * A weighted directed edge. + */ + private static class Edge { + + /** + * Target node + */ + public final Node target; + + /** + * Edge weight + */ + public final double weight; + + /** + * Edge constructor + */ + public Edge(Node target, double weight) { + assert (target != null); + this.target = target; + this.weight = weight; + } + } +} diff --git a/Annotation/src/ie/dcu/image/AbstractImageOp.class b/Annotation/src/ie/dcu/image/AbstractImageOp.class new file mode 100644 index 0000000..9f0461b Binary files /dev/null and b/Annotation/src/ie/dcu/image/AbstractImageOp.class differ diff --git a/Annotation/src/ie/dcu/image/AbstractImageOp.java b/Annotation/src/ie/dcu/image/AbstractImageOp.java new file mode 100644 index 0000000..7a91060 --- /dev/null +++ b/Annotation/src/ie/dcu/image/AbstractImageOp.java @@ -0,0 +1,94 @@ +package ie.dcu.image; + +import ie.dcu.matrix.*; +import ie.dcu.matrix.Matrix.Type; + +/** + * Abstract implementation of an {@link ImageOp}. Subclasses should implement + * the {@link #processImage(MatrixProvider)} method. + * + * + * @author Kevin McGuinness + */ +public abstract class AbstractImageOp implements ImageOp { + + private MatrixProvider inputProvider; + private Matrix outputMatrix; + + /** + * Default constructor (does nothing). + */ + public AbstractImageOp() { + } + + /** + * Returns true if the output matrix is available. + */ + public boolean isProcessingComplete() { + return outputMatrix != null; + } + + /** + * Returns true if the input {@link MatrixProvider} has been + * set. + */ + public boolean isInputProviderSet() { + return inputProvider != null; + } + + /** + * Set the input provider. Clears the output {@link Matrix}. + * + * @see ImageOp#setInputProvider(MatrixProvider) + */ + public void setInputProvider(MatrixProvider provider) { + this.inputProvider = provider; + this.outputMatrix = null; + } + + /** + * Returns the input {@link MatrixProvider}. + * + * @return The input {@link MatrixProvider} or null if it has + * not been set. + */ + public MatrixProvider getInputProvider() { + return inputProvider; + } + + /** + * Returns the output {@link Matrix}. + * + * @return The output {@link Matrix} or null if it has not been + * set. + */ + protected Matrix getOutputMatrix() { + if (!isInputProviderSet()) { + throw new IllegalStateException("input provider not set"); + } + + if (!isProcessingComplete()) { + outputMatrix = processImage(getInputProvider()); + } + + return outputMatrix; + } + + public Matrix getMatrix(boolean alwaysCopy) { + return getMatrix(null, false); + } + + public Matrix getMatrix(Type type, boolean alwaysCopy) { + return getOutputMatrix().getMatrix(type, alwaysCopy); + } + + /** + * Process the image and return the results. + * + * @param imageProvider + * A class that can be used to obtain the input image. + * @return The result of the image operation. + */ + protected abstract Matrix processImage(MatrixProvider imageProvider); + +} diff --git a/Annotation/src/ie/dcu/image/ContourTracer$Candidate.class b/Annotation/src/ie/dcu/image/ContourTracer$Candidate.class new file mode 100644 index 0000000..31a9585 Binary files /dev/null and b/Annotation/src/ie/dcu/image/ContourTracer$Candidate.class differ diff --git a/Annotation/src/ie/dcu/image/ContourTracer.class b/Annotation/src/ie/dcu/image/ContourTracer.class new file mode 100644 index 0000000..70e41ee Binary files /dev/null and b/Annotation/src/ie/dcu/image/ContourTracer.class differ diff --git a/Annotation/src/ie/dcu/image/ContourTracer.java b/Annotation/src/ie/dcu/image/ContourTracer.java new file mode 100644 index 0000000..3bc95b4 --- /dev/null +++ b/Annotation/src/ie/dcu/image/ContourTracer.java @@ -0,0 +1,197 @@ +package ie.dcu.image; + +import ie.dcu.matrix.*; + +import java.awt.Polygon; +import java.util.*; + +import org.eclipse.swt.graphics.Point; + +/** + * Trace contours of objects in images. + * + * TODO: This class uses SWT points and AWT polygons... + * + * @author Kevin McGuinness + */ +public class ContourTracer { + + private final IntMatrix labels; + private final int nobjects; + + // Inversion table + private static final int[] INVERT = { 4,5,6,7,0,1,2,3 }; + + // Neighbor count + private static final int NEIGHBORS = 8; + + public ContourTracer(ByteMatrix mask, byte foregroundValue) { + ObjectLabeler mapper = new ObjectLabeler(); + mapper.setForegroundValue(foregroundValue); + nobjects = mapper.label(mask); + labels = mapper.getLabelMap(); + } + + public List trace() { + List polygons = new ArrayList(); + if (labels != null) { + doTrace(polygons); + } + return polygons; + } + + private void doTrace(List polygons) { + for (int i = 1; i <= nobjects; i++) { + Polygon polygon = trace(i); + if (polygon != null) { + polygons.add(polygon); + } + //break; + } + } + + + private Polygon trace(int object) { + Point e1 = findFirstObjectPixel(object); + + if (e1 != null) { + // First external border pixel is to the left + e1 = new Point(e1.x-1, e1.y); + + List pts = new ArrayList(); + pts.add(e1); + + // Find the second pixel + Candidate c = findFirstCandidate(e1, object); + + if (c != null) { + + Candidate next = new Candidate(c.pt, c.direction); + + do { + next = findNext(next.pt, next.direction, object); + pts.add(next.pt); + } while (!next.pt.equals(e1)); + } + + return toPolygon(pts); + } + + return null; + } + + private final Candidate findNext(Point pc, int dpc, int object) { + Candidate next = null; + + int dcp = INVERT[dpc]; + for (int r = 0; r < 7; r++) { + int de = (dcp + r) % NEIGHBORS; + int di = (dcp + r + 1) % NEIGHBORS; + Point pe = neighbour(pc, de); + Point pi = neighbour(pc, di); + if (isBackground(pe, object) && isObject(pi, object)) { + next = new Candidate(pe, de); + } + } + + return next; + } + + private final Point findFirstObjectPixel(int object) { + for (int y = 0; y < labels.rows; y++) { + for (int x = 0; x < labels.cols; x++) { + int label = labels.intAt(y, x); + if (label == object) { + return new Point(x, y); + } + } + } + + return null; + } + + static final class Candidate { + final Point pt; + final int direction; + + Candidate(Point pt, int direction) { + this.pt = new Point(pt.x, pt.y); + this.direction = direction; + } + } + + private final Candidate findFirstCandidate(Point p0, int object) { + + // Find the next pixel + for (int i = 4; i < NEIGHBORS; i++) { + Point p1 = neighbour(p0, i); + Point p2 = neighbour(p0, (i+1) % NEIGHBORS); + if (isBackground(p1, object) && isObject(p2, object)) { + return new Candidate(p1, i); + } + } + return null; + } + + + private final boolean isBackground(Point pt, int object) { + return !labels.hasIndex(pt.y, pt.x) || labels.intAt(pt.y, pt.x) != object; + } + + private final boolean isObject(Point pt, int label) { + return labels.hasIndex(pt.y, pt.x) && labels.intAt(pt.y, pt.x) == label; + } + + private final Point neighbour(Point pt, int n) { + Point np = new Point(pt.x, pt.y); + switch (n) { + case 0: + np.x++; + break; + case 1: + np.x++; + np.y--; + break; + case 2: + np.y--; + break; + case 3: + np.x--; + np.y--; + break; + case 4: + np.x--; + break; + case 5: + np.x--; + np.y++; + break; + case 6: + np.y++; + break; + case 7: + np.x++; + np.y++; + default: + assert (false); + } + return np; + } + + + private static Polygon toPolygon(List pts) { + Polygon poly = new Polygon(); + poly.npoints = pts.size(); + poly.xpoints = new int[pts.size()]; + poly.ypoints = new int[pts.size()]; + + int i = 0; + for (Point p : pts) { + poly.xpoints[i] = p.x; + poly.ypoints[i] = p.y; + i++; + } + return poly; + } +} + diff --git a/Annotation/src/ie/dcu/image/ImageOp.class b/Annotation/src/ie/dcu/image/ImageOp.class new file mode 100644 index 0000000..ddb4435 Binary files /dev/null and b/Annotation/src/ie/dcu/image/ImageOp.class differ diff --git a/Annotation/src/ie/dcu/image/ImageOp.java b/Annotation/src/ie/dcu/image/ImageOp.java new file mode 100644 index 0000000..b7d830d --- /dev/null +++ b/Annotation/src/ie/dcu/image/ImageOp.java @@ -0,0 +1,30 @@ +package ie.dcu.image; + +import ie.dcu.matrix.MatrixProvider; + +/** + * Interface for classes that implement operations on images. + * + * The following is an example of how it can be used: + *
+ *   ByteMatrix input = ... 
+ *   ImageOp op = createImageOp(); 
+ *   op.setInputProvider(input);
+ *   ByteMatrix matrix = (ByteMatrix) op.getMatrix(Matrix.Type.Byte, false);
+ * 
+ * + * The above assumes that createImageOp() creates and returns + * an instance of ImageOp. + * + * @author Kevin McGuinness + */ +public interface ImageOp extends MatrixProvider { + + /** + * Set the class that will provide the input for this image operation. + * + * @param provider + * A {@link MatrixProvider} instance. + */ + public void setInputProvider(MatrixProvider provider); +} diff --git a/Annotation/src/ie/dcu/image/ObjectLabeler.class b/Annotation/src/ie/dcu/image/ObjectLabeler.class new file mode 100644 index 0000000..d7f1cab Binary files /dev/null and b/Annotation/src/ie/dcu/image/ObjectLabeler.class differ diff --git a/Annotation/src/ie/dcu/image/ObjectLabeler.java b/Annotation/src/ie/dcu/image/ObjectLabeler.java new file mode 100644 index 0000000..cdfbad1 --- /dev/null +++ b/Annotation/src/ie/dcu/image/ObjectLabeler.java @@ -0,0 +1,197 @@ +package ie.dcu.image; + +import ie.dcu.matrix.*; +import ie.dcu.matrix.Matrix.Type; + +import java.util.Stack; + +/** + * Class to perform connected component analysis on a binary object mask and + * create a labeled map of connected components. + * + * Connected component analysis is performed using the 8-neighborhood rule. + * + * + * @author Kevin McGuinness + */ +public class ObjectLabeler implements MatrixProvider { + + /** + * Value of the background label in the label maps produced. + */ + public static final int BACKGROUND_LABEL = 0; + + /** + * Offsets of the row indices for each of the 8-neighbors + */ + private static final int[] Ni = { -1, -1, -1, 0, 0, 1, 1, 1 }; + + /** + * Offsets of the column values for each of the 8-neighbors + */ + private static final int[] Nj = { -1, 0, 1, -1, 1, -1, 0, 1 }; + + /** + * The label matrix. + */ + private IntMatrix labels; + + /** + * The number of objects found in the last labeling. + */ + private int objectCount; + + /** + * The value used to identify foreground pixels in the object mask. + */ + private byte foregroundValue; + + /** + * Construct an object labeler with a default foreground label value of 1. + */ + public ObjectLabeler() { + this((byte) 1); + } + + /** + * Construct an object labeler that identifies foreground pixels using the + * given value. + * + * @param foregroundValue + * The value used to identify foreground pixels in the mask. + */ + public ObjectLabeler(byte foregroundValue) { + this.objectCount = 0; + this.foregroundValue = foregroundValue; + } + + /** + * Get the foreground value used to identify foreground pixels in the mask. + */ + public byte getForegroundValue() { + return foregroundValue; + } + + /** + * Set the foreground value used to identify foreground pixels in the mask. + */ + public void setForegroundValue(byte value) { + foregroundValue = value; + } + + /** + * Return the number of objects found in the last labeling. + */ + public int getObjectCount() { + return objectCount; + } + + /** + * Returns the label map computed in the last labeling. This will be null + * if no labeling has been performed with this labeler. + */ + public IntMatrix getLabelMap() { + return labels; + } + + /** + * Compute the connected component labeling of the given binary mask. + * + * @param mask + * A binary matrix (non null). + * @return The number of objects found. + */ + public int label(ByteMatrix mask) { + labels = new IntMatrix(mask.rows, mask.cols); + + // Fill the object with the background label + labels.fill(BACKGROUND_LABEL); + + // Current label + int label = 0; + + // Labeling loop + for (int i = 0, k = 0; i < mask.rows; i++) { + for (int j = 0; j < mask.cols; j++, k++) { + + if (mask.values[k] == foregroundValue && + labels.values[k] == BACKGROUND_LABEL) + { + label++; + + // Unlabeled foreground pixel + doLabel(mask, i, j, label); + } + } + } + + // Set and return label count + return (objectCount = label); + } + + /** + * Internal routine for label propagation. + */ + private void doLabel(ByteMatrix mask, int i, int j, int label) { + + // Stack of indices to process + Stack stack = new Stack(); + stack.add(new Index2D(i, j)); + + // Processing loop + while (!stack.isEmpty()) { + + Index2D idx = stack.pop(); + + if (labels.intAt(idx) != BACKGROUND_LABEL) { + // Already labeled + continue; + } + + labels.setIntAt(idx, label); + + // iterate over neighbors + for (int k = 0; k < Ni.length; k++) { + i = idx.i + Ni[k]; + j = idx.j + Nj[k]; + + // Check in range + if (labels.hasIndex(i, j)) { + + int offset = labels.offsetOf(i, j); + + if (labels.values[offset] == BACKGROUND_LABEL && + mask.values[offset] == foregroundValue) + { + stack.push(new Index2D(i, j)); + } + } + } + } + } + + /** + * Implementation of matrix provider. + */ + public Matrix getMatrix(boolean alwaysCopy) { + return getMatrix(null, alwaysCopy); + } + + /** + * Implementation of matrix provider. + */ + public Matrix getMatrix(Type type, boolean alwaysCopy) { + if (labels == null) { + throw new IllegalStateException(); + } + + return labels.getMatrix(type, alwaysCopy); + } + + /** + * Implementation of matrix provider. + */ + public Type getDefaultMatrixType() { + return labels.getDefaultMatrixType(); + } +} diff --git a/Annotation/src/ie/dcu/image/binary/AbstractBinaryImageOp.class b/Annotation/src/ie/dcu/image/binary/AbstractBinaryImageOp.class new file mode 100644 index 0000000..09c8d21 Binary files /dev/null and b/Annotation/src/ie/dcu/image/binary/AbstractBinaryImageOp.class differ diff --git a/Annotation/src/ie/dcu/image/binary/AbstractBinaryImageOp.java b/Annotation/src/ie/dcu/image/binary/AbstractBinaryImageOp.java new file mode 100644 index 0000000..3c3edc5 --- /dev/null +++ b/Annotation/src/ie/dcu/image/binary/AbstractBinaryImageOp.java @@ -0,0 +1,98 @@ +package ie.dcu.image.binary; + +import ie.dcu.image.AbstractImageOp; +import ie.dcu.matrix.*; + +/** + * Abstract implementation of the {@link BinaryImageOp} interface. + * + * Subclasses should implement either the {@link #processImage(ByteMatrix)} or + * the {@link #processImage(MatrixProvider)} method. + * + * @author Kevin McGuinness + */ +public abstract class AbstractBinaryImageOp extends AbstractImageOp + implements BinaryImageOp +{ + /** + * The value that should be interpreted by the implementor as a background + * pixel. + */ + protected byte backgroundValue; + + /** + * The value that should be interpreted by the implementor as a foreground + * pixel. + */ + protected byte foregroundValue; + + /** + * Flag indicating that the default implementation of + * {@link #processImage(MatrixProvider)} should request a copy of the input + * {@link Matrix}. + */ + private boolean requestInputCopy; + + /** + * Default constructor. Sets the {@link #foregroundValue} and + * {@link #backgroundValue} values to + * {@link BinaryImageOp#DEFAULT_FOREGROUND_VALUE} and + * {@link BinaryImageOp#DEFAULT_BACKGROUND_VALUE} + */ + public AbstractBinaryImageOp() { + backgroundValue = DEFAULT_BACKGROUND_VALUE; + foregroundValue = DEFAULT_FOREGROUND_VALUE; + requestInputCopy = true; + } + + /** + * Set a flag indicating whether the default implementation of + * {@link #processImage(MatrixProvider)} should pass a copy of the input to + * matrix to {@link #processImage(ByteMatrix)}. + * + * @param requestInputCopy + * true to have {@link #processImage(ByteMatrix)} + * request a copy of the input matrix, false otherwise. + */ + protected void setRequestInputCopy(boolean requestInputCopy) { + this.requestInputCopy = requestInputCopy; + } + + public void setBackgroundValue(byte backgroundValue) { + this.backgroundValue = backgroundValue; + } + + /** + * Returns the value that should be interpreted by the implementor as + * a background pixel. + */ + public byte getBackgroundValue() { + return backgroundValue; + } + + public void setForegroundValue(byte foregroundValue) { + this.foregroundValue = foregroundValue; + } + + /** + * Returns the value that should be interpreted by the implementor as + * a foreground pixel. + */ + public byte getForegroundValue() { + return foregroundValue; + } + + protected final Matrix processImage(MatrixProvider inputProvider) { + Matrix matrix = inputProvider.getMatrix(Matrix.Type.Byte, requestInputCopy); + return processImage((ByteMatrix) matrix); + } + + /** + * Process the image and return the results. + * + * @param input + * The input byte matrix. + * @return The result of the image operation. + */ + protected abstract Matrix processImage(ByteMatrix input); +} diff --git a/Annotation/src/ie/dcu/image/binary/BinaryImageOp.class b/Annotation/src/ie/dcu/image/binary/BinaryImageOp.class new file mode 100644 index 0000000..edc1b05 Binary files /dev/null and b/Annotation/src/ie/dcu/image/binary/BinaryImageOp.class differ diff --git a/Annotation/src/ie/dcu/image/binary/BinaryImageOp.java b/Annotation/src/ie/dcu/image/binary/BinaryImageOp.java new file mode 100644 index 0000000..b7d8c37 --- /dev/null +++ b/Annotation/src/ie/dcu/image/binary/BinaryImageOp.java @@ -0,0 +1,39 @@ +package ie.dcu.image.binary; + +import ie.dcu.image.ImageOp; + +/** + * A specialization of {@link ImageOp} for binary images. + * + * @author Kevin McGuinness + */ +public interface BinaryImageOp extends ImageOp { + + /** + * The default byte value that the image operation should consider to + * foreground. + */ + public static final byte DEFAULT_BACKGROUND_VALUE = 0; + + /** + * The default byte value that the image operation should consider to + * background. + */ + public static final byte DEFAULT_FOREGROUND_VALUE = 1; + + /** + * Set the value that the image operation should consider to be foreground. + * + * @param foregroundValue + * A byte value. + */ + public void setForegroundValue(byte foregroundValue); + + /** + * Set the value that the image operation should consider to be background. + * + * @param backgroundValue + * A byte value. + */ + public void setBackgroundValue(byte backgroundValue); +} diff --git a/Annotation/src/ie/dcu/image/binary/DistanceTransformOp.class b/Annotation/src/ie/dcu/image/binary/DistanceTransformOp.class new file mode 100644 index 0000000..d45091b Binary files /dev/null and b/Annotation/src/ie/dcu/image/binary/DistanceTransformOp.class differ diff --git a/Annotation/src/ie/dcu/image/binary/DistanceTransformOp.java b/Annotation/src/ie/dcu/image/binary/DistanceTransformOp.java new file mode 100644 index 0000000..b904f2d --- /dev/null +++ b/Annotation/src/ie/dcu/image/binary/DistanceTransformOp.java @@ -0,0 +1,34 @@ +package ie.dcu.image.binary; + +import ie.dcu.image.dt.DistanceTransform; +import ie.dcu.matrix.*; +import ie.dcu.matrix.Matrix.Type; + +/** + * Distance transform operation. This class is a {@link BinaryImageOp} wrapper + * for the {@link DistanceTransform} object. + * + * @author Kevin McGuinness + */ +public class DistanceTransformOp extends AbstractBinaryImageOp { + private boolean computeSquareTransform; + + public DistanceTransformOp() { + setRequestInputCopy(false); + computeSquareTransform = false; + } + + @Override + protected Matrix processImage(ByteMatrix input) { + DistanceTransform transform = new DistanceTransform(); + transform.init(input, foregroundValue); + if (computeSquareTransform) { + return transform.computeSquareTransform(); + } + return transform.computeTransform(); + } + + public Type getDefaultMatrixType() { + return Matrix.Type.Double; + } +} diff --git a/Annotation/src/ie/dcu/image/binary/MedialAxisTransformOp.class b/Annotation/src/ie/dcu/image/binary/MedialAxisTransformOp.class new file mode 100644 index 0000000..f0b07b7 Binary files /dev/null and b/Annotation/src/ie/dcu/image/binary/MedialAxisTransformOp.class differ diff --git a/Annotation/src/ie/dcu/image/binary/MedialAxisTransformOp.java b/Annotation/src/ie/dcu/image/binary/MedialAxisTransformOp.java new file mode 100644 index 0000000..6daed38 --- /dev/null +++ b/Annotation/src/ie/dcu/image/binary/MedialAxisTransformOp.java @@ -0,0 +1,98 @@ +package ie.dcu.image.binary; + +import ie.dcu.image.dt.DistanceTransform; +import ie.dcu.matrix.*; +import ie.dcu.matrix.Matrix.Type; + +/** + * Implementation of the Medial Axis Transform (MAT). + * + * Computes the MAT by finding the Laplace of the square distance transform. + * + * @author Kevin McGuinness + */ +public class MedialAxisTransformOp extends AbstractBinaryImageOp { + private boolean simpleLaplace = false; + + @Override + protected Matrix processImage(ByteMatrix input) { + DistanceTransform transform = new DistanceTransform(); + transform.init(input, foregroundValue); + IntMatrix dt = transform.computeSquareTransform(); + return laplace(dt).clamp(0, Integer.MAX_VALUE); + } + + + private IntMatrix laplace(IntMatrix m) { + return simpleLaplace ? laplace4(m) : laplace8(m); + } + + private IntMatrix laplace4(IntMatrix m) { + + IntMatrix result = new IntMatrix(m.rows, m.cols); + + int n0, n1, n2, n3; + for (int i = 0; i < m.rows; i++) { + + n0 = (i != 0) ? 1 : 0; + n3 = (i != m.rows - 1) ? 1 : 0; + + for (int j = 0; j < m.cols; j++) { + + n1 = (j != 0) ? 1 : 0; + n2 = (j != m.cols-1) ? 1 : 0; + + int value = (n0 + n1 + n2 + n3) * m.intAt(i, j); + value -= (n0 != 0) ? m.intAt(i-1, j) : 0; + value -= (n1 != 0) ? m.intAt(i, j-1) : 0; + value -= (n2 != 0) ? m.intAt(i, j+1) : 0; + value -= (n3 != 0) ? m.intAt(i+1, j) : 0; + result.setIntAt(i, j, value); + } + } + + return result; + } + + private IntMatrix laplace8(IntMatrix m) { + IntMatrix result = new IntMatrix(m.rows, m.cols); + + int a = m.rows - 1; + int b = m.cols - 1; + + int n0, n1, n2, n3, n4, n5, n6, n7; + for (int i = 0; i < m.rows; i++) { + + for (int j = 0; j < m.cols; j++) { + + n0 = (i != 0 && j != 0) ? 1 : 0; + n1 = (i != 0) ? 1 : 0; + n2 = (i != 0 && j != b) ? 1 : 0; + n3 = (j != 0) ? 1 : 0; + n4 = (j != b) ? 1 : 0; + n5 = (i != a && j != 0) ? 1 : 0; + n6 = (i != a) ? 1 : 0; + n7 = (i != a && j != b) ? 1 : 0; + + int w = (n0 + n1 + n2 + n3 + n4 + n5 + n6 + n7); + int v = w * m.intAt(i, j); + + v -= (n0 != 0) ? m.intAt(i-1, j-1) : 0; + v -= (n1 != 0) ? m.intAt(i-1, j ) : 0; + v -= (n2 != 0) ? m.intAt(i-1, j+1) : 0; + v -= (n3 != 0) ? m.intAt(i , j-1) : 0; + v -= (n4 != 0) ? m.intAt(i , j+1) : 0; + v -= (n5 != 0) ? m.intAt(i+1, j-1) : 0; + v -= (n6 != 0) ? m.intAt(i+1, j ) : 0; + v -= (n7 != 0) ? m.intAt(i+1, j+1) : 0; + + result.setIntAt(i, j, v); + } + } + return result; + } + + public Type getDefaultMatrixType() { + return Matrix.Type.Int; + } +} diff --git a/Annotation/src/ie/dcu/image/binary/MorphOp$Close.class b/Annotation/src/ie/dcu/image/binary/MorphOp$Close.class new file mode 100644 index 0000000..396ddec Binary files /dev/null and b/Annotation/src/ie/dcu/image/binary/MorphOp$Close.class differ diff --git a/Annotation/src/ie/dcu/image/binary/MorphOp$Dilate.class b/Annotation/src/ie/dcu/image/binary/MorphOp$Dilate.class new file mode 100644 index 0000000..7711b68 Binary files /dev/null and b/Annotation/src/ie/dcu/image/binary/MorphOp$Dilate.class differ diff --git a/Annotation/src/ie/dcu/image/binary/MorphOp$Edge.class b/Annotation/src/ie/dcu/image/binary/MorphOp$Edge.class new file mode 100644 index 0000000..d8da859 Binary files /dev/null and b/Annotation/src/ie/dcu/image/binary/MorphOp$Edge.class differ diff --git a/Annotation/src/ie/dcu/image/binary/MorphOp$Erode.class b/Annotation/src/ie/dcu/image/binary/MorphOp$Erode.class new file mode 100644 index 0000000..8220046 Binary files /dev/null and b/Annotation/src/ie/dcu/image/binary/MorphOp$Erode.class differ diff --git a/Annotation/src/ie/dcu/image/binary/MorphOp$Open.class b/Annotation/src/ie/dcu/image/binary/MorphOp$Open.class new file mode 100644 index 0000000..0206fd4 Binary files /dev/null and b/Annotation/src/ie/dcu/image/binary/MorphOp$Open.class differ diff --git a/Annotation/src/ie/dcu/image/binary/MorphOp$Smooth.class b/Annotation/src/ie/dcu/image/binary/MorphOp$Smooth.class new file mode 100644 index 0000000..f7dc57c Binary files /dev/null and b/Annotation/src/ie/dcu/image/binary/MorphOp$Smooth.class differ diff --git a/Annotation/src/ie/dcu/image/binary/MorphOp.class b/Annotation/src/ie/dcu/image/binary/MorphOp.class new file mode 100644 index 0000000..d13427d Binary files /dev/null and b/Annotation/src/ie/dcu/image/binary/MorphOp.class differ diff --git a/Annotation/src/ie/dcu/image/binary/MorphOp.java b/Annotation/src/ie/dcu/image/binary/MorphOp.java new file mode 100644 index 0000000..cda8789 --- /dev/null +++ b/Annotation/src/ie/dcu/image/binary/MorphOp.java @@ -0,0 +1,476 @@ +package ie.dcu.image.binary; + +import ie.dcu.matrix.*; +import ie.dcu.matrix.Matrix.Type; + +/** + * Base class for binary morphological operations. + * + * Implementations of different morphological operations are given as the static + * inner classes. + * + * @author Kevin McGuinness + */ +public abstract class MorphOp extends AbstractBinaryImageOp { + + /** + * The structuring element for the morph. + */ + protected ByteMatrix structuringElement; + + /** + * Get the structuring element. + * + * @return the structuring element (may be null). + */ + public ByteMatrix getStructuringElement() { + return structuringElement; + } + + /** + * Set the structuring element. + * + * @param se + * A structuring element (can be null). + */ + public void setStructuringElement(ByteMatrix se) { + this.structuringElement = se; + } + + /** + * Perform a basic morph-op on the given matrix. + * + * The operation will be either an erode or dilate depending + * on the values of the a and b parameters. + * + * @param matrix + * The matrix to operate on (will be modified). + * @param a + * Either the foregroundValue or the backgroundValue + * @param b + * Either the foregroundValue or the backgroundValue + * @return + * The modified input matrix. + */ + protected static ByteMatrix morph( + final ByteMatrix matrix, + final byte a, + final byte b + ) { + + final byte[] im = matrix.values; + + // Right pixel + for (int i = 0; i < matrix.rows; i++) { + final int off = i * matrix.cols; + + for (int j = 0; j < matrix.cols - 1; j++) { + final int idx = off + j; + + if (im[idx] == b && im[idx+1] == a) { + im[idx] = a; + } + } + } + + // Left pixel + for (int i = 0; i < matrix.rows; i++) { + final int off = i * matrix.cols; + + for (int j = matrix.cols - 1; j > 0; j--) { + final int idx = off + j; + + if (im[idx] == b && im[idx-1] == a) { + im[idx] = a; + } + } + } + + // Below pixel + for (int i = 0; i < matrix.rows - 1; i++) { + final int off = i * matrix.cols; + + for (int j = 0; j < matrix.cols; j++) { + final int idx = off + j; + + if (im[idx] == b && im[idx + matrix.cols] == a) { + im[idx] = a; + } + } + } + + // Above pixel + for (int i = matrix.rows - 1; i > 0; i--) { + final int off = i * matrix.cols; + + for (int j = 0; j < matrix.cols; j++) { + final int idx = off + j; + + if (im[idx] == b && im[idx - matrix.cols] == a) { + im[idx] = a; + } + } + } + + return matrix; + } + + /** + * Perform a binary morphological operation with a structuring element. + * + * @param matrix + * The input matrix to morph (not modified). + * @param se + * The structuring element. + * @param a + * Either the foreground or background value. + * @param b + * Either the foreground or background value. + * @return A matrix containing the result of the morph. + */ + protected static ByteMatrix morph( + final ByteMatrix matrix, + final ByteMatrix se, + final byte a, + final byte b) + { + final ByteMatrix result = + new ByteMatrix(matrix.rows, matrix.cols); + result.fill(a); + + for (int i = 0, k = 0; i < matrix.rows; i++) { + for (int j = 0; j < matrix.cols; j++, k++) { + + if (matrix.values[k] == b) { + byte value = b; + + int im_i0 = i - (se.rows >> 1); + int im_j0 = j - (se.cols >> 1); + int se_i0 = im_i0 < 0 ? -im_i0 : 0; + int se_j0 = im_j0 < 0 ? -im_j0 : 0; + + if (im_i0 < 0) { + im_i0 = 0; + } + + if (im_j0 < 0) { + im_j0 = 0; + } + + // Iterate over structuring element + outer: + for (int se_i = se_i0, im_i = im_i0; + se_i < se.rows && im_i < matrix.rows; + se_i++, im_i++) + { + int off1 = se_i * se.cols; + int off2 = im_i * matrix.cols; + + for (int se_j = se_j0, im_j = im_j0; + se_j < se.cols && im_j < matrix.cols; + se_j++, im_j++) + { + if (se.values[off1 + se_j] != 0 && + matrix.values[off2 + im_j] == a) + { + value = a; + break outer; + } + } + } + + // Set value + result.values[k] = value; + } + } + } + + return result; + } + + /** + * Applies the morphological dilate operator. + * + * @param matrix + * The matrix to operate on (will be modified). + * @return the input matrix + */ + protected ByteMatrix dilate(ByteMatrix matrix) { + return morph(matrix, foregroundValue, backgroundValue); + } + + /** + * Perform a morphological dilation using the given structuring element + * + * @param matrix + * The matrix to operate on (will not be modified). + * @param se + * The structuring element + * @return A matrix containing the result of the morph. + */ + protected ByteMatrix dilate(ByteMatrix matrix, ByteMatrix se) { + if (se == null) { + return dilate(matrix.clone()); + } + + return morph(matrix, se, foregroundValue, backgroundValue); + } + + + /** + * Applies the morphological erode operator. + * + * @param matrix + * The matrix to operate on (will be modified). + * @return the input matrix + */ + protected ByteMatrix erode(ByteMatrix matrix) { + return morph(matrix, backgroundValue, foregroundValue); + } + + /** + * Perform a morphological erosion using the given structuring element + * + * @param matrix + * The matrix to operate on (will not be modified). + * @param se + * The structuring element + * @return A matrix containing the result of the morph. + */ + protected ByteMatrix erode(ByteMatrix matrix, ByteMatrix se) { + if (se == null) { + return erode(matrix.clone()); + } + + return morph(matrix, se, backgroundValue, foregroundValue); + } + + + /** + * Applies the morphological open operator. + * + * @param matrix + * The matrix to operate on (will be modified). + * @return the input matrix + */ + protected ByteMatrix open(ByteMatrix matrix) { + return dilate(erode(matrix)); + } + + /** + * Perform a morphological open using the given structuring element + * + * @param matrix + * The matrix to operate on (will not be modified). + * @param se + * The structuring element + * @return A matrix containing the result of the morph. + */ + protected ByteMatrix open(ByteMatrix matrix, ByteMatrix se) { + if (se == null) { + return open(matrix.clone()); + } + return dilate(erode(matrix, se), se); + } + + /** + * Applies the morphological open operator. + * + * @param matrix + * The matrix to operate on (will be modified). + * @return the input matrix + */ + protected ByteMatrix close(ByteMatrix matrix) { + return erode(dilate(matrix)); + } + + /** + * Perform a morphological close using the given structuring element + * + * @param matrix + * The matrix to operate on (will not be modified). + * @param se + * The structuring element + * @return A matrix containing the result of the morph. + */ + protected ByteMatrix close(ByteMatrix matrix, ByteMatrix se) { + if (se == null) { + return close(matrix.clone()); + } + return erode(dilate(matrix, se), se); + } + + /** + * Applies the morphological smooth operator. + * + * @param matrix + * The matrix to operate on (will be modified). + * @return the input matrix + */ + protected ByteMatrix smooth(ByteMatrix matrix) { + return close(open(matrix)); + } + + /** + * Perform a morphological smooth using the given structuring element + * + * @param matrix + * The matrix to operate on (will not be modified). + * @param se + * The structuring element + * @return A matrix containing the result of the morph. + */ + protected ByteMatrix smooth(ByteMatrix matrix, ByteMatrix se) { + if (se == null) { + return smooth(matrix.clone()); + } + return close(open(matrix, se), se); + } + + /** + * Applies the morphological edge operator. + * + * @param matrix + * The matrix to operate on (will be modified). + * @return the input matrix + */ + protected ByteMatrix edge(ByteMatrix matrix) { + + // Dilate + dilate(matrix); + + // Erode to temporary + ByteMatrix erosion = erode(matrix.clone()); + + // Remove eroded mask + for (int i = 0; i < matrix.size; i++) { + if (erosion.values[i] == foregroundValue) { + matrix.values[i] = backgroundValue; + } + } + + return matrix; + } + + /** + * Perform a morphological edge using the given structuring element + * + * @param matrix + * The matrix to operate on (will not be modified). + * @param se + * The structuring element + * @return A matrix containing the result of the morph. + */ + protected ByteMatrix edge(ByteMatrix matrix, ByteMatrix se) { + if (se == null) { + return edge(matrix.clone()); + } + + // Dilate + dilate(matrix, se); + + // Erode to temporary + ByteMatrix erosion = erode(matrix.clone(), se); + + // Remove eroded mask + for (int i = 0; i < matrix.size; i++) { + if (erosion.values[i] == foregroundValue) { + matrix.values[i] = backgroundValue; + } + } + + return matrix; + } + + /* + * (non-Javadoc) + * @see ie.dcu.cdvp.matrix.MatrixProvider#getDefaultMatrixType() + */ + public Type getDefaultMatrixType() { + return Matrix.Type.Byte; + } + + /** + * Binary morphological erosion operation. + */ + public static class Erode extends MorphOp { + + @Override + protected ByteMatrix processImage(ByteMatrix input) { + if (structuringElement == null) { + return erode(input); + } + return erode(input, structuringElement); + } + } + + /** + * Binary morphological dilation operation. + */ + public static class Dilate extends MorphOp { + + @Override + protected ByteMatrix processImage(ByteMatrix input) { + if (structuringElement == null) { + return dilate(input); + } + return dilate(input, structuringElement); + } + } + + /** + * Binary morphological open operation. + */ + public static class Open extends MorphOp { + + @Override + protected ByteMatrix processImage(ByteMatrix input) { + if (structuringElement == null) { + return open(input); + } + return open(input, structuringElement); + } + } + + /** + * Binary morphological close operation. + */ + public static class Close extends MorphOp { + + @Override + protected ByteMatrix processImage(ByteMatrix input) { + if (structuringElement == null) { + return close(input); + } + return close(input, structuringElement); + } + } + + /** + * Binary morphological smooth operation. + */ + public static class Smooth extends MorphOp { + + @Override + protected ByteMatrix processImage(ByteMatrix input) { + if (structuringElement == null) { + return smooth(input); + } + return smooth(input, structuringElement); + } + } + + /** + * Binary morphological edge operation. + */ + public static class Edge extends MorphOp { + + @Override + protected ByteMatrix processImage(ByteMatrix input) { + if (structuringElement == null) { + return edge(input); + } + return edge(input, structuringElement); + } + } +} diff --git a/Annotation/src/ie/dcu/image/colormap/ColorMap.class b/Annotation/src/ie/dcu/image/colormap/ColorMap.class new file mode 100644 index 0000000..3e1feff Binary files /dev/null and b/Annotation/src/ie/dcu/image/colormap/ColorMap.class differ diff --git a/Annotation/src/ie/dcu/image/colormap/ColorMap.java b/Annotation/src/ie/dcu/image/colormap/ColorMap.java new file mode 100644 index 0000000..39b45aa --- /dev/null +++ b/Annotation/src/ie/dcu/image/colormap/ColorMap.java @@ -0,0 +1,83 @@ +package ie.dcu.image.colormap; + +import java.io.Serializable; + +import org.eclipse.swt.graphics.*; + +/** + * Base class for color maps. + * + * @author Kevin McGuinness + */ +public class ColorMap implements Serializable { + + /** + * Serialization UID + */ + private static final long serialVersionUID = 3514876556837016224L; + + /** + * Color look up table. N x 3 components representing the + * RGB values. + */ + protected final float[][] lut; + + /** + * Create a color map of the given size. + */ + protected ColorMap(int size) { + this.lut = new float[size][3]; + } + + /** + * Create a color map from the given look up table. + */ + public ColorMap(float[][] lut) { + if (lut == null) { + throw new NullPointerException("lut == null"); + } + + for (int i = 0; i < lut.length; i++) { + if (lut[i].length != 3) { + throw new IllegalArgumentException(); + } + } + + this.lut = lut; + } + + public int size() { + return lut.length; + } + + public final float red(int index) { + return lut[index][0]; + } + + public final float green(int index) { + return lut[index][1]; + } + + public final float blue(int index) { + return lut[index][2]; + } + + public final RGB rgb(int index) { + int r = (int) (lut[index][0] * 255); + int g = (int) (lut[index][1] * 255); + int b = (int) (lut[index][2] * 255); + return new RGB(r, g, b); + } + + public PaletteData createPaletteData() { + RGB[] palette = new RGB[lut.length]; + for (int i = 0; i < lut.length; i++) { + int r = (int) (lut[i][0] * 255); + int g = (int) (lut[i][1] * 255); + int b = (int) (lut[i][2] * 255); + palette[i] = new RGB(r, g, b); + } + return new PaletteData(palette); + } + +} diff --git a/Annotation/src/ie/dcu/image/colormap/ColorMaps$SpecCache.class b/Annotation/src/ie/dcu/image/colormap/ColorMaps$SpecCache.class new file mode 100644 index 0000000..6fe78ea Binary files /dev/null and b/Annotation/src/ie/dcu/image/colormap/ColorMaps$SpecCache.class differ diff --git a/Annotation/src/ie/dcu/image/colormap/ColorMaps.class b/Annotation/src/ie/dcu/image/colormap/ColorMaps.class new file mode 100644 index 0000000..d80bc26 Binary files /dev/null and b/Annotation/src/ie/dcu/image/colormap/ColorMaps.class differ diff --git a/Annotation/src/ie/dcu/image/colormap/ColorMaps.java b/Annotation/src/ie/dcu/image/colormap/ColorMaps.java new file mode 100644 index 0000000..9bcb818 --- /dev/null +++ b/Annotation/src/ie/dcu/image/colormap/ColorMaps.java @@ -0,0 +1,969 @@ +package ie.dcu.image.colormap; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * A set of predefined color maps. + * + * @author Kevin McGuinness + */ +public final class ColorMaps { + + /** + * Specification for the "binary" color map. + */ + private static final float[][][] SPEC_BINARY = { + { // R + { 0.000000f, 1.000000f, 1.000000f }, + { 1.000000f, 0.000000f, 0.000000f } }, + { // G + { 0.000000f, 1.000000f, 1.000000f }, + { 1.000000f, 0.000000f, 0.000000f } }, + { // B + { 0.000000f, 1.000000f, 1.000000f }, + { 1.000000f, 0.000000f, 0.000000f } } + }; + + /** + * Specification for the "grey" color map. + */ + private static final float[][][] SPEC_GREY = { + { // R + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // B + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 1.000000f, 1.000000f } } + }; + + /** + * Specification for the "autumn" color map. + */ + private static final float[][][] SPEC_AUTUMN = { + { // R + { 0.000000f, 1.000000f, 1.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // B + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 0.000000f, 0.000000f } } + }; + + /** + * Specification for the "bone" color map. + */ + private static final float[][][] SPEC_BONE = { + { // R + { 0.000000f, 0.000000f, 0.000000f }, + { 0.746032f, 0.652778f, 0.652778f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 0.365079f, 0.319444f, 0.319444f }, + { 0.746032f, 0.777778f, 0.777778f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // B + { 0.000000f, 0.000000f, 0.000000f }, + { 0.365079f, 0.444444f, 0.444444f }, + { 1.000000f, 1.000000f, 1.000000f } } + }; + + /** + * Specification for the "cool" color map. + */ + private static final float[][][] SPEC_COOL = { + { // R + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // G + { 0.000000f, 1.000000f, 1.000000f }, + { 1.000000f, 0.000000f, 0.000000f } }, + { // B + { 0.000000f, 1.000000f, 1.000000f }, + { 1.000000f, 1.000000f, 1.000000f } } + }; + + /** + * Specification for the "copper" color map. + */ + private static final float[][][] SPEC_COPPER = { + { // R + { 0.000000f, 0.000000f, 0.000000f }, + { 0.809524f, 1.000000f, 1.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 0.781200f, 0.781200f } }, + { // B + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 0.497500f, 0.497500f } } + }; + + /** + * Specification for the "flag" color map. + */ + private static final float[][][] SPEC_FLAG = { + { // R + { 0.000000f, 1.000000f, 1.000000f }, + { 0.015873f, 1.000000f, 1.000000f }, + { 0.031746f, 0.000000f, 0.000000f }, + { 0.047619f, 0.000000f, 0.000000f }, + { 0.063492f, 1.000000f, 1.000000f }, + { 0.079365f, 1.000000f, 1.000000f }, + { 0.095238f, 0.000000f, 0.000000f }, + { 0.111111f, 0.000000f, 0.000000f }, + { 0.126984f, 1.000000f, 1.000000f }, + { 0.142857f, 1.000000f, 1.000000f }, + { 0.158730f, 0.000000f, 0.000000f }, + { 0.174603f, 0.000000f, 0.000000f }, + { 0.190476f, 1.000000f, 1.000000f }, + { 0.206349f, 1.000000f, 1.000000f }, + { 0.222222f, 0.000000f, 0.000000f }, + { 0.238095f, 0.000000f, 0.000000f }, + { 0.253968f, 1.000000f, 1.000000f }, + { 0.269841f, 1.000000f, 1.000000f }, + { 0.285714f, 0.000000f, 0.000000f }, + { 0.301587f, 0.000000f, 0.000000f }, + { 0.317460f, 1.000000f, 1.000000f }, + { 0.333333f, 1.000000f, 1.000000f }, + { 0.349206f, 0.000000f, 0.000000f }, + { 0.365079f, 0.000000f, 0.000000f }, + { 0.380952f, 1.000000f, 1.000000f }, + { 0.396825f, 1.000000f, 1.000000f }, + { 0.412698f, 0.000000f, 0.000000f }, + { 0.428571f, 0.000000f, 0.000000f }, + { 0.444444f, 1.000000f, 1.000000f }, + { 0.460317f, 1.000000f, 1.000000f }, + { 0.476190f, 0.000000f, 0.000000f }, + { 0.492063f, 0.000000f, 0.000000f }, + { 0.507937f, 1.000000f, 1.000000f }, + { 0.523810f, 1.000000f, 1.000000f }, + { 0.539683f, 0.000000f, 0.000000f }, + { 0.555556f, 0.000000f, 0.000000f }, + { 0.571429f, 1.000000f, 1.000000f }, + { 0.587302f, 1.000000f, 1.000000f }, + { 0.603175f, 0.000000f, 0.000000f }, + { 0.619048f, 0.000000f, 0.000000f }, + { 0.634921f, 1.000000f, 1.000000f }, + { 0.650794f, 1.000000f, 1.000000f }, + { 0.666667f, 0.000000f, 0.000000f }, + { 0.682540f, 0.000000f, 0.000000f }, + { 0.698413f, 1.000000f, 1.000000f }, + { 0.714286f, 1.000000f, 1.000000f }, + { 0.730159f, 0.000000f, 0.000000f }, + { 0.746032f, 0.000000f, 0.000000f }, + { 0.761905f, 1.000000f, 1.000000f }, + { 0.777778f, 1.000000f, 1.000000f }, + { 0.793651f, 0.000000f, 0.000000f }, + { 0.809524f, 0.000000f, 0.000000f }, + { 0.825397f, 1.000000f, 1.000000f }, + { 0.841270f, 1.000000f, 1.000000f }, + { 0.857143f, 0.000000f, 0.000000f }, + { 0.873016f, 0.000000f, 0.000000f }, + { 0.888889f, 1.000000f, 1.000000f }, + { 0.904762f, 1.000000f, 1.000000f }, + { 0.920635f, 0.000000f, 0.000000f }, + { 0.936508f, 0.000000f, 0.000000f }, + { 0.952381f, 1.000000f, 1.000000f }, + { 0.968254f, 1.000000f, 1.000000f }, + { 0.984127f, 0.000000f, 0.000000f }, + { 1.000000f, 0.000000f, 0.000000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 0.015873f, 1.000000f, 1.000000f }, + { 0.031746f, 0.000000f, 0.000000f }, + { 0.063492f, 0.000000f, 0.000000f }, + { 0.079365f, 1.000000f, 1.000000f }, + { 0.095238f, 0.000000f, 0.000000f }, + { 0.126984f, 0.000000f, 0.000000f }, + { 0.142857f, 1.000000f, 1.000000f }, + { 0.158730f, 0.000000f, 0.000000f }, + { 0.190476f, 0.000000f, 0.000000f }, + { 0.206349f, 1.000000f, 1.000000f }, + { 0.222222f, 0.000000f, 0.000000f }, + { 0.253968f, 0.000000f, 0.000000f }, + { 0.269841f, 1.000000f, 1.000000f }, + { 0.285714f, 0.000000f, 0.000000f }, + { 0.317460f, 0.000000f, 0.000000f }, + { 0.333333f, 1.000000f, 1.000000f }, + { 0.349206f, 0.000000f, 0.000000f }, + { 0.380952f, 0.000000f, 0.000000f }, + { 0.396825f, 1.000000f, 1.000000f }, + { 0.412698f, 0.000000f, 0.000000f }, + { 0.444444f, 0.000000f, 0.000000f }, + { 0.460317f, 1.000000f, 1.000000f }, + { 0.476190f, 0.000000f, 0.000000f }, + { 0.507937f, 0.000000f, 0.000000f }, + { 0.523810f, 1.000000f, 1.000000f }, + { 0.539683f, 0.000000f, 0.000000f }, + { 0.571429f, 0.000000f, 0.000000f }, + { 0.587302f, 1.000000f, 1.000000f }, + { 0.603175f, 0.000000f, 0.000000f }, + { 0.634921f, 0.000000f, 0.000000f }, + { 0.650794f, 1.000000f, 1.000000f }, + { 0.666667f, 0.000000f, 0.000000f }, + { 0.698413f, 0.000000f, 0.000000f }, + { 0.714286f, 1.000000f, 1.000000f }, + { 0.730159f, 0.000000f, 0.000000f }, + { 0.761905f, 0.000000f, 0.000000f }, + { 0.777778f, 1.000000f, 1.000000f }, + { 0.793651f, 0.000000f, 0.000000f }, + { 0.825397f, 0.000000f, 0.000000f }, + { 0.841270f, 1.000000f, 1.000000f }, + { 0.857143f, 0.000000f, 0.000000f }, + { 0.888889f, 0.000000f, 0.000000f }, + { 0.904762f, 1.000000f, 1.000000f }, + { 0.920635f, 0.000000f, 0.000000f }, + { 0.952381f, 0.000000f, 0.000000f }, + { 0.968254f, 1.000000f, 1.000000f }, + { 0.984127f, 0.000000f, 0.000000f }, + { 1.000000f, 0.000000f, 0.000000f } }, + { // B + { 0.000000f, 0.000000f, 0.000000f }, + { 0.015873f, 1.000000f, 1.000000f }, + { 0.031746f, 1.000000f, 1.000000f }, + { 0.047619f, 0.000000f, 0.000000f }, + { 0.063492f, 0.000000f, 0.000000f }, + { 0.079365f, 1.000000f, 1.000000f }, + { 0.095238f, 1.000000f, 1.000000f }, + { 0.111111f, 0.000000f, 0.000000f }, + { 0.126984f, 0.000000f, 0.000000f }, + { 0.142857f, 1.000000f, 1.000000f }, + { 0.158730f, 1.000000f, 1.000000f }, + { 0.174603f, 0.000000f, 0.000000f }, + { 0.190476f, 0.000000f, 0.000000f }, + { 0.206349f, 1.000000f, 1.000000f }, + { 0.222222f, 1.000000f, 1.000000f }, + { 0.238095f, 0.000000f, 0.000000f }, + { 0.253968f, 0.000000f, 0.000000f }, + { 0.269841f, 1.000000f, 1.000000f }, + { 0.285714f, 1.000000f, 1.000000f }, + { 0.301587f, 0.000000f, 0.000000f }, + { 0.317460f, 0.000000f, 0.000000f }, + { 0.333333f, 1.000000f, 1.000000f }, + { 0.349206f, 1.000000f, 1.000000f }, + { 0.365079f, 0.000000f, 0.000000f }, + { 0.380952f, 0.000000f, 0.000000f }, + { 0.396825f, 1.000000f, 1.000000f }, + { 0.412698f, 1.000000f, 1.000000f }, + { 0.428571f, 0.000000f, 0.000000f }, + { 0.444444f, 0.000000f, 0.000000f }, + { 0.460317f, 1.000000f, 1.000000f }, + { 0.476190f, 1.000000f, 1.000000f }, + { 0.492063f, 0.000000f, 0.000000f }, + { 0.507937f, 0.000000f, 0.000000f }, + { 0.523810f, 1.000000f, 1.000000f }, + { 0.539683f, 1.000000f, 1.000000f }, + { 0.555556f, 0.000000f, 0.000000f }, + { 0.571429f, 0.000000f, 0.000000f }, + { 0.587302f, 1.000000f, 1.000000f }, + { 0.603175f, 1.000000f, 1.000000f }, + { 0.619048f, 0.000000f, 0.000000f }, + { 0.634921f, 0.000000f, 0.000000f }, + { 0.650794f, 1.000000f, 1.000000f }, + { 0.666667f, 1.000000f, 1.000000f }, + { 0.682540f, 0.000000f, 0.000000f }, + { 0.698413f, 0.000000f, 0.000000f }, + { 0.714286f, 1.000000f, 1.000000f }, + { 0.730159f, 1.000000f, 1.000000f }, + { 0.746032f, 0.000000f, 0.000000f }, + { 0.761905f, 0.000000f, 0.000000f }, + { 0.777778f, 1.000000f, 1.000000f }, + { 0.793651f, 1.000000f, 1.000000f }, + { 0.809524f, 0.000000f, 0.000000f }, + { 0.825397f, 0.000000f, 0.000000f }, + { 0.841270f, 1.000000f, 1.000000f }, + { 0.857143f, 1.000000f, 1.000000f }, + { 0.873016f, 0.000000f, 0.000000f }, + { 0.888889f, 0.000000f, 0.000000f }, + { 0.904762f, 1.000000f, 1.000000f }, + { 0.920635f, 1.000000f, 1.000000f }, + { 0.936508f, 0.000000f, 0.000000f }, + { 0.952381f, 0.000000f, 0.000000f }, + { 0.968254f, 1.000000f, 1.000000f }, + { 0.984127f, 1.000000f, 1.000000f }, + { 1.000000f, 0.000000f, 0.000000f } } + }; + + /** + * Specification for the "hot" color map. + */ + private static final float[][][] SPEC_HOT = { + { // R + { 0.000000f, 0.041600f, 0.041600f }, + { 0.365079f, 1.000000f, 1.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 0.365079f, 0.000000f, 0.000000f }, + { 0.746032f, 1.000000f, 1.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // B + { 0.000000f, 0.000000f, 0.000000f }, + { 0.746032f, 0.000000f, 0.000000f }, + { 1.000000f, 1.000000f, 1.000000f } } + }; + + /** + * Specification for the "jet" color map. + */ + private static final float[][][] SPEC_JET = { + { // R + { 0.000000f, 0.000000f, 0.000000f }, + { 0.350000f, 0.000000f, 0.000000f }, + { 0.660000f, 1.000000f, 1.000000f }, + { 0.890000f, 1.000000f, 1.000000f }, + { 1.000000f, 0.500000f, 0.500000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 0.125000f, 0.000000f, 0.000000f }, + { 0.375000f, 1.000000f, 1.000000f }, + { 0.640000f, 1.000000f, 1.000000f }, + { 0.910000f, 0.000000f, 0.000000f }, + { 1.000000f, 0.000000f, 0.000000f } }, + { // B + { 0.000000f, 0.500000f, 0.500000f }, + { 0.110000f, 1.000000f, 1.000000f }, + { 0.340000f, 1.000000f, 1.000000f }, + { 0.650000f, 0.000000f, 0.000000f }, + { 1.000000f, 0.000000f, 0.000000f } } + }; + + /** + * Specification for the "pink" color map. + */ + private static final float[][][] SPEC_PINK = { + { // R + { 0.000000f, 0.117800f, 0.117800f }, + { 0.015873f, 0.195857f, 0.195857f }, + { 0.031746f, 0.250661f, 0.250661f }, + { 0.047619f, 0.295468f, 0.295468f }, + { 0.063492f, 0.334324f, 0.334324f }, + { 0.079365f, 0.369112f, 0.369112f }, + { 0.095238f, 0.400892f, 0.400892f }, + { 0.111111f, 0.430331f, 0.430331f }, + { 0.126984f, 0.457882f, 0.457882f }, + { 0.142857f, 0.483867f, 0.483867f }, + { 0.158730f, 0.508525f, 0.508525f }, + { 0.174603f, 0.532042f, 0.532042f }, + { 0.190476f, 0.554563f, 0.554563f }, + { 0.206349f, 0.576204f, 0.576204f }, + { 0.222222f, 0.597061f, 0.597061f }, + { 0.238095f, 0.617213f, 0.617213f }, + { 0.253968f, 0.636729f, 0.636729f }, + { 0.269841f, 0.655663f, 0.655663f }, + { 0.285714f, 0.674066f, 0.674066f }, + { 0.301587f, 0.691980f, 0.691980f }, + { 0.317460f, 0.709441f, 0.709441f }, + { 0.333333f, 0.726483f, 0.726483f }, + { 0.349206f, 0.743134f, 0.743134f }, + { 0.365079f, 0.759421f, 0.759421f }, + { 0.380952f, 0.766356f, 0.766356f }, + { 0.396825f, 0.773229f, 0.773229f }, + { 0.412698f, 0.780042f, 0.780042f }, + { 0.428571f, 0.786796f, 0.786796f }, + { 0.444444f, 0.793492f, 0.793492f }, + { 0.460317f, 0.800132f, 0.800132f }, + { 0.476190f, 0.806718f, 0.806718f }, + { 0.492063f, 0.813250f, 0.813250f }, + { 0.507937f, 0.819730f, 0.819730f }, + { 0.523810f, 0.826160f, 0.826160f }, + { 0.539683f, 0.832539f, 0.832539f }, + { 0.555556f, 0.838870f, 0.838870f }, + { 0.571429f, 0.845154f, 0.845154f }, + { 0.587302f, 0.851392f, 0.851392f }, + { 0.603175f, 0.857584f, 0.857584f }, + { 0.619048f, 0.863731f, 0.863731f }, + { 0.634921f, 0.869835f, 0.869835f }, + { 0.650794f, 0.875897f, 0.875897f }, + { 0.666667f, 0.881917f, 0.881917f }, + { 0.682540f, 0.887896f, 0.887896f }, + { 0.698413f, 0.893835f, 0.893835f }, + { 0.714286f, 0.899735f, 0.899735f }, + { 0.730159f, 0.905597f, 0.905597f }, + { 0.746032f, 0.911421f, 0.911421f }, + { 0.761905f, 0.917208f, 0.917208f }, + { 0.777778f, 0.922958f, 0.922958f }, + { 0.793651f, 0.928673f, 0.928673f }, + { 0.809524f, 0.934353f, 0.934353f }, + { 0.825397f, 0.939999f, 0.939999f }, + { 0.841270f, 0.945611f, 0.945611f }, + { 0.857143f, 0.951190f, 0.951190f }, + { 0.873016f, 0.956736f, 0.956736f }, + { 0.888889f, 0.962250f, 0.962250f }, + { 0.904762f, 0.967733f, 0.967733f }, + { 0.920635f, 0.973185f, 0.973185f }, + { 0.936508f, 0.978607f, 0.978607f }, + { 0.952381f, 0.983999f, 0.983999f }, + { 0.968254f, 0.989361f, 0.989361f }, + { 0.984127f, 0.994695f, 0.994695f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 0.015873f, 0.102869f, 0.102869f }, + { 0.031746f, 0.145479f, 0.145479f }, + { 0.047619f, 0.178174f, 0.178174f }, + { 0.063492f, 0.205738f, 0.205738f }, + { 0.079365f, 0.230022f, 0.230022f }, + { 0.095238f, 0.251976f, 0.251976f }, + { 0.111111f, 0.272166f, 0.272166f }, + { 0.126984f, 0.290957f, 0.290957f }, + { 0.142857f, 0.308607f, 0.308607f }, + { 0.158730f, 0.325300f, 0.325300f }, + { 0.174603f, 0.341178f, 0.341178f }, + { 0.190476f, 0.356348f, 0.356348f }, + { 0.206349f, 0.370899f, 0.370899f }, + { 0.222222f, 0.384900f, 0.384900f }, + { 0.238095f, 0.398410f, 0.398410f }, + { 0.253968f, 0.411476f, 0.411476f }, + { 0.269841f, 0.424139f, 0.424139f }, + { 0.285714f, 0.436436f, 0.436436f }, + { 0.301587f, 0.448395f, 0.448395f }, + { 0.317460f, 0.460044f, 0.460044f }, + { 0.333333f, 0.471405f, 0.471405f }, + { 0.349206f, 0.482498f, 0.482498f }, + { 0.365079f, 0.493342f, 0.493342f }, + { 0.380952f, 0.517549f, 0.517549f }, + { 0.396825f, 0.540674f, 0.540674f }, + { 0.412698f, 0.562849f, 0.562849f }, + { 0.428571f, 0.584183f, 0.584183f }, + { 0.444444f, 0.604765f, 0.604765f }, + { 0.460317f, 0.624669f, 0.624669f }, + { 0.476190f, 0.643958f, 0.643958f }, + { 0.492063f, 0.662687f, 0.662687f }, + { 0.507937f, 0.680900f, 0.680900f }, + { 0.523810f, 0.698638f, 0.698638f }, + { 0.539683f, 0.715937f, 0.715937f }, + { 0.555556f, 0.732828f, 0.732828f }, + { 0.571429f, 0.749338f, 0.749338f }, + { 0.587302f, 0.765493f, 0.765493f }, + { 0.603175f, 0.781313f, 0.781313f }, + { 0.619048f, 0.796819f, 0.796819f }, + { 0.634921f, 0.812029f, 0.812029f }, + { 0.650794f, 0.826960f, 0.826960f }, + { 0.666667f, 0.841625f, 0.841625f }, + { 0.682540f, 0.856040f, 0.856040f }, + { 0.698413f, 0.870216f, 0.870216f }, + { 0.714286f, 0.884164f, 0.884164f }, + { 0.730159f, 0.897896f, 0.897896f }, + { 0.746032f, 0.911421f, 0.911421f }, + { 0.761905f, 0.917208f, 0.917208f }, + { 0.777778f, 0.922958f, 0.922958f }, + { 0.793651f, 0.928673f, 0.928673f }, + { 0.809524f, 0.934353f, 0.934353f }, + { 0.825397f, 0.939999f, 0.939999f }, + { 0.841270f, 0.945611f, 0.945611f }, + { 0.857143f, 0.951190f, 0.951190f }, + { 0.873016f, 0.956736f, 0.956736f }, + { 0.888889f, 0.962250f, 0.962250f }, + { 0.904762f, 0.967733f, 0.967733f }, + { 0.920635f, 0.973185f, 0.973185f }, + { 0.936508f, 0.978607f, 0.978607f }, + { 0.952381f, 0.983999f, 0.983999f }, + { 0.968254f, 0.989361f, 0.989361f }, + { 0.984127f, 0.994695f, 0.994695f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // B + { 0.000000f, 0.000000f, 0.000000f }, + { 0.015873f, 0.102869f, 0.102869f }, + { 0.031746f, 0.145479f, 0.145479f }, + { 0.047619f, 0.178174f, 0.178174f }, + { 0.063492f, 0.205738f, 0.205738f }, + { 0.079365f, 0.230022f, 0.230022f }, + { 0.095238f, 0.251976f, 0.251976f }, + { 0.111111f, 0.272166f, 0.272166f }, + { 0.126984f, 0.290957f, 0.290957f }, + { 0.142857f, 0.308607f, 0.308607f }, + { 0.158730f, 0.325300f, 0.325300f }, + { 0.174603f, 0.341178f, 0.341178f }, + { 0.190476f, 0.356348f, 0.356348f }, + { 0.206349f, 0.370899f, 0.370899f }, + { 0.222222f, 0.384900f, 0.384900f }, + { 0.238095f, 0.398410f, 0.398410f }, + { 0.253968f, 0.411476f, 0.411476f }, + { 0.269841f, 0.424139f, 0.424139f }, + { 0.285714f, 0.436436f, 0.436436f }, + { 0.301587f, 0.448395f, 0.448395f }, + { 0.317460f, 0.460044f, 0.460044f }, + { 0.333333f, 0.471405f, 0.471405f }, + { 0.349206f, 0.482498f, 0.482498f }, + { 0.365079f, 0.493342f, 0.493342f }, + { 0.380952f, 0.503953f, 0.503953f }, + { 0.396825f, 0.514344f, 0.514344f }, + { 0.412698f, 0.524531f, 0.524531f }, + { 0.428571f, 0.534522f, 0.534522f }, + { 0.444444f, 0.544331f, 0.544331f }, + { 0.460317f, 0.553966f, 0.553966f }, + { 0.476190f, 0.563436f, 0.563436f }, + { 0.492063f, 0.572750f, 0.572750f }, + { 0.507937f, 0.581914f, 0.581914f }, + { 0.523810f, 0.590937f, 0.590937f }, + { 0.539683f, 0.599824f, 0.599824f }, + { 0.555556f, 0.608581f, 0.608581f }, + { 0.571429f, 0.617213f, 0.617213f }, + { 0.587302f, 0.625727f, 0.625727f }, + { 0.603175f, 0.634126f, 0.634126f }, + { 0.619048f, 0.642416f, 0.642416f }, + { 0.634921f, 0.650600f, 0.650600f }, + { 0.650794f, 0.658682f, 0.658682f }, + { 0.666667f, 0.666667f, 0.666667f }, + { 0.682540f, 0.674556f, 0.674556f }, + { 0.698413f, 0.682355f, 0.682355f }, + { 0.714286f, 0.690066f, 0.690066f }, + { 0.730159f, 0.697691f, 0.697691f }, + { 0.746032f, 0.705234f, 0.705234f }, + { 0.761905f, 0.727166f, 0.727166f }, + { 0.777778f, 0.748455f, 0.748455f }, + { 0.793651f, 0.769156f, 0.769156f }, + { 0.809524f, 0.789314f, 0.789314f }, + { 0.825397f, 0.808969f, 0.808969f }, + { 0.841270f, 0.828159f, 0.828159f }, + { 0.857143f, 0.846913f, 0.846913f }, + { 0.873016f, 0.865261f, 0.865261f }, + { 0.888889f, 0.883229f, 0.883229f }, + { 0.904762f, 0.900837f, 0.900837f }, + { 0.920635f, 0.918109f, 0.918109f }, + { 0.936508f, 0.935061f, 0.935061f }, + { 0.952381f, 0.951711f, 0.951711f }, + { 0.968254f, 0.968075f, 0.968075f }, + { 0.984127f, 0.984167f, 0.984167f }, + { 1.000000f, 1.000000f, 1.000000f } } + }; + + /** + * Specification for the "prism" color map. + */ + private static final float[][][] SPEC_PRISM = { + { // R + { 0.000000f, 1.000000f, 1.000000f }, + { 0.031746f, 1.000000f, 1.000000f }, + { 0.047619f, 0.000000f, 0.000000f }, + { 0.063492f, 0.000000f, 0.000000f }, + { 0.079365f, 0.666667f, 0.666667f }, + { 0.095238f, 1.000000f, 1.000000f }, + { 0.126984f, 1.000000f, 1.000000f }, + { 0.142857f, 0.000000f, 0.000000f }, + { 0.158730f, 0.000000f, 0.000000f }, + { 0.174603f, 0.666667f, 0.666667f }, + { 0.190476f, 1.000000f, 1.000000f }, + { 0.222222f, 1.000000f, 1.000000f }, + { 0.238095f, 0.000000f, 0.000000f }, + { 0.253968f, 0.000000f, 0.000000f }, + { 0.269841f, 0.666667f, 0.666667f }, + { 0.285714f, 1.000000f, 1.000000f }, + { 0.317460f, 1.000000f, 1.000000f }, + { 0.333333f, 0.000000f, 0.000000f }, + { 0.349206f, 0.000000f, 0.000000f }, + { 0.365079f, 0.666667f, 0.666667f }, + { 0.380952f, 1.000000f, 1.000000f }, + { 0.412698f, 1.000000f, 1.000000f }, + { 0.428571f, 0.000000f, 0.000000f }, + { 0.444444f, 0.000000f, 0.000000f }, + { 0.460317f, 0.666667f, 0.666667f }, + { 0.476190f, 1.000000f, 1.000000f }, + { 0.507937f, 1.000000f, 1.000000f }, + { 0.523810f, 0.000000f, 0.000000f }, + { 0.539683f, 0.000000f, 0.000000f }, + { 0.555556f, 0.666667f, 0.666667f }, + { 0.571429f, 1.000000f, 1.000000f }, + { 0.603175f, 1.000000f, 1.000000f }, + { 0.619048f, 0.000000f, 0.000000f }, + { 0.634921f, 0.000000f, 0.000000f }, + { 0.650794f, 0.666667f, 0.666667f }, + { 0.666667f, 1.000000f, 1.000000f }, + { 0.698413f, 1.000000f, 1.000000f }, + { 0.714286f, 0.000000f, 0.000000f }, + { 0.730159f, 0.000000f, 0.000000f }, + { 0.746032f, 0.666667f, 0.666667f }, + { 0.761905f, 1.000000f, 1.000000f }, + { 0.793651f, 1.000000f, 1.000000f }, + { 0.809524f, 0.000000f, 0.000000f }, + { 0.825397f, 0.000000f, 0.000000f }, + { 0.841270f, 0.666667f, 0.666667f }, + { 0.857143f, 1.000000f, 1.000000f }, + { 0.888889f, 1.000000f, 1.000000f }, + { 0.904762f, 0.000000f, 0.000000f }, + { 0.920635f, 0.000000f, 0.000000f }, + { 0.936508f, 0.666667f, 0.666667f }, + { 0.952381f, 1.000000f, 1.000000f }, + { 0.984127f, 1.000000f, 1.000000f }, + { 1.000000f, 0.000000f, 0.000000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 0.031746f, 1.000000f, 1.000000f }, + { 0.047619f, 1.000000f, 1.000000f }, + { 0.063492f, 0.000000f, 0.000000f }, + { 0.095238f, 0.000000f, 0.000000f }, + { 0.126984f, 1.000000f, 1.000000f }, + { 0.142857f, 1.000000f, 1.000000f }, + { 0.158730f, 0.000000f, 0.000000f }, + { 0.190476f, 0.000000f, 0.000000f }, + { 0.222222f, 1.000000f, 1.000000f }, + { 0.238095f, 1.000000f, 1.000000f }, + { 0.253968f, 0.000000f, 0.000000f }, + { 0.285714f, 0.000000f, 0.000000f }, + { 0.317460f, 1.000000f, 1.000000f }, + { 0.333333f, 1.000000f, 1.000000f }, + { 0.349206f, 0.000000f, 0.000000f }, + { 0.380952f, 0.000000f, 0.000000f }, + { 0.412698f, 1.000000f, 1.000000f }, + { 0.428571f, 1.000000f, 1.000000f }, + { 0.444444f, 0.000000f, 0.000000f }, + { 0.476190f, 0.000000f, 0.000000f }, + { 0.507937f, 1.000000f, 1.000000f }, + { 0.523810f, 1.000000f, 1.000000f }, + { 0.539683f, 0.000000f, 0.000000f }, + { 0.571429f, 0.000000f, 0.000000f }, + { 0.603175f, 1.000000f, 1.000000f }, + { 0.619048f, 1.000000f, 1.000000f }, + { 0.634921f, 0.000000f, 0.000000f }, + { 0.666667f, 0.000000f, 0.000000f }, + { 0.698413f, 1.000000f, 1.000000f }, + { 0.714286f, 1.000000f, 1.000000f }, + { 0.730159f, 0.000000f, 0.000000f }, + { 0.761905f, 0.000000f, 0.000000f }, + { 0.793651f, 1.000000f, 1.000000f }, + { 0.809524f, 1.000000f, 1.000000f }, + { 0.825397f, 0.000000f, 0.000000f }, + { 0.857143f, 0.000000f, 0.000000f }, + { 0.888889f, 1.000000f, 1.000000f }, + { 0.904762f, 1.000000f, 1.000000f }, + { 0.920635f, 0.000000f, 0.000000f }, + { 0.952381f, 0.000000f, 0.000000f }, + { 0.984127f, 1.000000f, 1.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // B + { 0.000000f, 0.000000f, 0.000000f }, + { 0.047619f, 0.000000f, 0.000000f }, + { 0.063492f, 1.000000f, 1.000000f }, + { 0.079365f, 1.000000f, 1.000000f }, + { 0.095238f, 0.000000f, 0.000000f }, + { 0.142857f, 0.000000f, 0.000000f }, + { 0.158730f, 1.000000f, 1.000000f }, + { 0.174603f, 1.000000f, 1.000000f }, + { 0.190476f, 0.000000f, 0.000000f }, + { 0.238095f, 0.000000f, 0.000000f }, + { 0.253968f, 1.000000f, 1.000000f }, + { 0.269841f, 1.000000f, 1.000000f }, + { 0.285714f, 0.000000f, 0.000000f }, + { 0.333333f, 0.000000f, 0.000000f }, + { 0.349206f, 1.000000f, 1.000000f }, + { 0.365079f, 1.000000f, 1.000000f }, + { 0.380952f, 0.000000f, 0.000000f }, + { 0.428571f, 0.000000f, 0.000000f }, + { 0.444444f, 1.000000f, 1.000000f }, + { 0.460317f, 1.000000f, 1.000000f }, + { 0.476190f, 0.000000f, 0.000000f }, + { 0.523810f, 0.000000f, 0.000000f }, + { 0.539683f, 1.000000f, 1.000000f }, + { 0.555556f, 1.000000f, 1.000000f }, + { 0.571429f, 0.000000f, 0.000000f }, + { 0.619048f, 0.000000f, 0.000000f }, + { 0.634921f, 1.000000f, 1.000000f }, + { 0.650794f, 1.000000f, 1.000000f }, + { 0.666667f, 0.000000f, 0.000000f }, + { 0.714286f, 0.000000f, 0.000000f }, + { 0.730159f, 1.000000f, 1.000000f }, + { 0.746032f, 1.000000f, 1.000000f }, + { 0.761905f, 0.000000f, 0.000000f }, + { 0.809524f, 0.000000f, 0.000000f }, + { 0.825397f, 1.000000f, 1.000000f }, + { 0.841270f, 1.000000f, 1.000000f }, + { 0.857143f, 0.000000f, 0.000000f }, + { 0.904762f, 0.000000f, 0.000000f }, + { 0.920635f, 1.000000f, 1.000000f }, + { 0.936508f, 1.000000f, 1.000000f }, + { 0.952381f, 0.000000f, 0.000000f }, + { 1.000000f, 0.000000f, 0.000000f } } + }; + + /** + * Specification for the "spring" color map. + */ + private static final float[][][] SPEC_SPRING = { + { // R + { 0.000000f, 1.000000f, 1.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // B + { 0.000000f, 1.000000f, 1.000000f }, + { 1.000000f, 0.000000f, 0.000000f } } + }; + + /** + * Specification for the "summer" color map. + */ + private static final float[][][] SPEC_SUMMER = { + { // R + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // G + { 0.000000f, 0.500000f, 0.500000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // B + { 0.000000f, 0.400000f, 0.400000f }, + { 1.000000f, 0.400000f, 0.400000f } } + }; + + /** + * Specification for the "winter" color map. + */ + private static final float[][][] SPEC_WINTER = { + { // R + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 0.000000f, 0.000000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 1.000000f, 1.000000f, 1.000000f } }, + { // B + { 0.000000f, 1.000000f, 1.000000f }, + { 1.000000f, 0.500000f, 0.500000f } } + }; + + /** + * Specification for the "spectral" color map. + */ + private static final float[][][] SPEC_SPECTRAL = { + { // R + { 0.000000f, 0.000000f, 0.000000f }, + { 0.050000f, 0.466700f, 0.466700f }, + { 0.100000f, 0.533300f, 0.533300f }, + { 0.150000f, 0.000000f, 0.000000f }, + { 0.200000f, 0.000000f, 0.000000f }, + { 0.250000f, 0.000000f, 0.000000f }, + { 0.300000f, 0.000000f, 0.000000f }, + { 0.350000f, 0.000000f, 0.000000f }, + { 0.400000f, 0.000000f, 0.000000f }, + { 0.450000f, 0.000000f, 0.000000f }, + { 0.500000f, 0.000000f, 0.000000f }, + { 0.550000f, 0.000000f, 0.000000f }, + { 0.600000f, 0.000000f, 0.000000f }, + { 0.650000f, 0.733300f, 0.733300f }, + { 0.700000f, 0.933300f, 0.933300f }, + { 0.750000f, 1.000000f, 1.000000f }, + { 0.800000f, 1.000000f, 1.000000f }, + { 0.850000f, 1.000000f, 1.000000f }, + { 0.900000f, 0.866700f, 0.866700f }, + { 0.950000f, 0.800000f, 0.800000f }, + { 1.000000f, 0.800000f, 0.800000f } }, + { // G + { 0.000000f, 0.000000f, 0.000000f }, + { 0.050000f, 0.000000f, 0.000000f }, + { 0.100000f, 0.000000f, 0.000000f }, + { 0.150000f, 0.000000f, 0.000000f }, + { 0.200000f, 0.000000f, 0.000000f }, + { 0.250000f, 0.466700f, 0.466700f }, + { 0.300000f, 0.600000f, 0.600000f }, + { 0.350000f, 0.666700f, 0.666700f }, + { 0.400000f, 0.666700f, 0.666700f }, + { 0.450000f, 0.600000f, 0.600000f }, + { 0.500000f, 0.733300f, 0.733300f }, + { 0.550000f, 0.866700f, 0.866700f }, + { 0.600000f, 1.000000f, 1.000000f }, + { 0.650000f, 1.000000f, 1.000000f }, + { 0.700000f, 0.933300f, 0.933300f }, + { 0.750000f, 0.800000f, 0.800000f }, + { 0.800000f, 0.600000f, 0.600000f }, + { 0.850000f, 0.000000f, 0.000000f }, + { 0.900000f, 0.000000f, 0.000000f }, + { 0.950000f, 0.000000f, 0.000000f }, + { 1.000000f, 0.800000f, 0.800000f } }, + { // B + { 0.000000f, 0.000000f, 0.000000f }, + { 0.050000f, 0.533300f, 0.533300f }, + { 0.100000f, 0.600000f, 0.600000f }, + { 0.150000f, 0.666700f, 0.666700f }, + { 0.200000f, 0.866700f, 0.866700f }, + { 0.250000f, 0.866700f, 0.866700f }, + { 0.300000f, 0.866700f, 0.866700f }, + { 0.350000f, 0.666700f, 0.666700f }, + { 0.400000f, 0.533300f, 0.533300f }, + { 0.450000f, 0.000000f, 0.000000f }, + { 0.500000f, 0.000000f, 0.000000f }, + { 0.550000f, 0.000000f, 0.000000f }, + { 0.600000f, 0.000000f, 0.000000f }, + { 0.650000f, 0.000000f, 0.000000f }, + { 0.700000f, 0.000000f, 0.000000f }, + { 0.750000f, 0.000000f, 0.000000f }, + { 0.800000f, 0.000000f, 0.000000f }, + { 0.850000f, 0.000000f, 0.000000f }, + { 0.900000f, 0.000000f, 0.000000f }, + { 0.950000f, 0.000000f, 0.000000f }, + { 1.000000f, 0.800000f, 0.800000f } } + }; + + private static class SpecCache { + final float[][][] spec; + ColorMap map; + + SpecCache(float[][][] spec) { + this.spec = spec; + } + }; + + private static final Map cache = + new HashMap(); + + static { + cache.put("binary", new SpecCache(SPEC_BINARY)); + cache.put("grey", new SpecCache(SPEC_GREY)); + cache.put("autumn", new SpecCache(SPEC_AUTUMN)); + cache.put("bone", new SpecCache(SPEC_BONE)); + cache.put("cool", new SpecCache(SPEC_COOL)); + cache.put("copper", new SpecCache(SPEC_COPPER)); + cache.put("flag", new SpecCache(SPEC_FLAG)); + cache.put("hot", new SpecCache(SPEC_HOT)); + cache.put("jet", new SpecCache(SPEC_JET)); + cache.put("pink", new SpecCache(SPEC_PINK)); + cache.put("prism", new SpecCache(SPEC_PRISM)); + cache.put("spring", new SpecCache(SPEC_SPRING)); + cache.put("summer", new SpecCache(SPEC_SUMMER)); + cache.put("winter", new SpecCache(SPEC_WINTER)); + cache.put("spectral", new SpecCache(SPEC_SPECTRAL)); + } + + /** + * Size of the predefined maps returned by this class + */ + public static final int MAP_SIZE = 256; + + /** + * Returns the (unmodifiable) set of predefined map names. + */ + public static Set names() { + return Collections.unmodifiableSet(cache.keySet()); + } + + /** + * Get a color map by name. + * + * @param name + * The color map names + * @return The color map. + */ + public static ColorMap get(String name) { + if (cache.containsKey(name)) { + SpecCache item = cache.get(name); + if (item.map == null) { + item.map = new LinearColorMap(MAP_SIZE, item.spec); + } + return item.map; + } + return null; + } + + /** + * Returns the "binary" color map + */ + public static ColorMap binary() { + return get("binary"); + } + + /** + * Returns the "grey" color map + */ + public static ColorMap grey() { + return get("grey"); + } + + /** + * Returns the "autumn" color map + */ + public static ColorMap autumn() { + return get("autumn"); + } + + /** + * Returns the "bone" color map + */ + public static ColorMap bone() { + return get("bone"); + } + + /** + * Returns the "cool" color map + */ + public static ColorMap cool() { + return get("cool"); + } + + /** + * Returns the "copper" color map + */ + public static ColorMap copper() { + return get("copper"); + } + + /** + * Returns the "flag" color map + */ + public static ColorMap flag() { + return get("flag"); + } + + /** + * Returns the "hot" color map + */ + public static ColorMap hot() { + return get("hot"); + } + + /** + * Returns the "jet" color map + */ + public static ColorMap jet() { + return get("jet"); + } + + /** + * Returns the "pink" color map + */ + public static ColorMap pink() { + return get("pink"); + } + + /** + * Returns the "prism" color map + */ + public static ColorMap prism() { + return get("prism"); + } + + /** + * Returns the "spring" color map + */ + public static ColorMap spring() { + return get("spring"); + } + + /** + * Returns the "summer" color map + */ + public static ColorMap summer() { + return get("summer"); + } + + /** + * Returns the "winter" color map + */ + public static ColorMap winter() { + return get("winter"); + } + + /** + * Returns the "spectral" color map + */ + public static ColorMap spectral() { + return get("spectral"); + } +} diff --git a/Annotation/src/ie/dcu/image/colormap/LinearColorMap.class b/Annotation/src/ie/dcu/image/colormap/LinearColorMap.class new file mode 100644 index 0000000..e0ea566 Binary files /dev/null and b/Annotation/src/ie/dcu/image/colormap/LinearColorMap.class differ diff --git a/Annotation/src/ie/dcu/image/colormap/LinearColorMap.java b/Annotation/src/ie/dcu/image/colormap/LinearColorMap.java new file mode 100644 index 0000000..fbddfd7 --- /dev/null +++ b/Annotation/src/ie/dcu/image/colormap/LinearColorMap.java @@ -0,0 +1,110 @@ +package ie.dcu.image.colormap; + +import java.util.Arrays; + +/** + * A linear segment color map. + * + * @author Kevin McGuinness + */ +public class LinearColorMap extends ColorMap { + + private static final long serialVersionUID = -7024754461124096870L; + + public LinearColorMap(int size, + float[][] rspec, + float[][] gspec, + float[][] bspec) + { + super(size); // me :-P + + float[] rvals = mapping(size, rspec); + for (int i = 0; i < size; i++) { + lut[i][0] = rvals[i]; + } + + float[] gvals = mapping(size, gspec); + for (int i = 0; i < size; i++) { + lut[i][1] = gvals[i]; + } + + float[] bvals = mapping(size, bspec); + for (int i = 0; i < size; i++) { + lut[i][2] = bvals[i]; + } + } + + public LinearColorMap(int size, float[][][] spec) { + this(size, spec[0], spec[1], spec[2]); + } + + private static float[] mapping(int n, float[][] spec) { + final int X = 0; + final int Y0 = 1; + final int Y1 = 2; + + // Non null + if (spec == null) { + throw new NullPointerException(); + } + + // Non empty + if (spec.length == 0) { + throw new IllegalArgumentException("spec empty"); + } + + // Number of cols must be 3 + for (int i = 0; i < spec.length; i++) { + if (spec[i].length != 3) { + throw new IllegalArgumentException("number of cols must be 3"); + } + } + + // X value must start at zero and end at 1 + if (spec[0][X] != 0.0 || spec[spec.length-1][X] != 1.0) { + throw new IllegalArgumentException("x value must start at zero and end at 1"); + } + + // X value must be increasing + for (int i = 1; i < spec.length; i++) { + if (spec[i][X] < spec[i-1][X]) { + throw new IllegalArgumentException("x value must be increasing"); + } + } + + float[] lut = new float[n]; + Arrays.fill(lut, 0.0f); + + lut[0] = clip(spec[0][Y1]); + + // x values by 255 + float[] x = new float[spec.length]; + for (int i = 0; i < spec.length; i++) { + x[i] = spec[i][X] * (n-1); + } + + // Indices + int[] idx = new int[n]; + for (int i = 0, j = 0; i < n; i++) { + while (j != x.length && x[j] < i) { + j++; + } + idx[i] = j; + } + + for (int i = 1; i < n-1; i++) { + float v = ((i - x[idx[i]-1]) / (x[idx[i]] - x[idx[i]-1])) + * (spec[idx[i]][Y0] - spec[idx[i]-1][Y1]) + spec[idx[i]-1][Y1]; + + lut[i] = clip(v); + } + + lut[n-1] = clip(spec[spec.length-1][Y0]); + + return lut; + } + + private static final float clip(float v) { + return (v < 0) ? 0 : (v > 1 ? 1 : v); + } +} diff --git a/Annotation/src/ie/dcu/image/dt/DistanceTransform.class b/Annotation/src/ie/dcu/image/dt/DistanceTransform.class new file mode 100644 index 0000000..cc4f5b1 Binary files /dev/null and b/Annotation/src/ie/dcu/image/dt/DistanceTransform.class differ diff --git a/Annotation/src/ie/dcu/image/dt/DistanceTransform.java b/Annotation/src/ie/dcu/image/dt/DistanceTransform.java new file mode 100644 index 0000000..0af6893 --- /dev/null +++ b/Annotation/src/ie/dcu/image/dt/DistanceTransform.java @@ -0,0 +1,416 @@ +package ie.dcu.image.dt; + +import ie.dcu.matrix.*; + + +/** + * Compute distance transforms using Meijster's algorithm: + * + * For details on the algorithm see: + * + *
+ *    A General Algorithm for Computing Distance Transforms in Linear Time.
+ *    Meijster et al. Computational Imaging and Vision (2000)
+ * 
+ * + * Meijster's algorithm appears to be the most efficient exact Euclidean + * distance transform algorithm in most situations. For more details see: + * + *
+ *    2D Euclidean distance transform algorithms: A comparative survey. 
+ *    Fabbri et al. ACM Computing Surveys (2008) vol. 40 (1) pp. 1-44
+ * 
+ * + * Note: If the matrix given for transform contains no background + * pixels, then each pixel will have a value of Integer.MAX_VALUE - rows**2 + * -cols**2 + * + * + * @author Kevin McGuinness + */ +public class DistanceTransform { + private IntMatrix matrix; + private int inf; + private boolean done; + + /** + * Create distance transform object + */ + public DistanceTransform() { + done = false; + } + + /** + * Returns true if the computation has been done. + */ + public boolean isComputed() { + return done; + } + + /** + * Returns true if the transform has been initialized. + */ + public boolean isInitialized() { + return matrix != null; + } + + + /** + * Private initializer + */ + private void init(Matrix m) { + this.matrix = new IntMatrix(m.rows, m.cols); + this.inf = Integer.MAX_VALUE - m.rows * m.rows - m.cols * m.cols; + this.done = false; + } + + /** + * Private routine to check if the transform is possible. + */ + private boolean isTransformPossible() { + // Cannot be called when done + assert (!done); + + for (int i = 0; i < matrix.size; i++) { + if (matrix.values[i] == 0) { + return true; + } + } + return false; + } + + /** + * Initialize transform with an integer matrix. + * + * @param m + * An integer matrix + * @param foregroundValue + * The value of a foreground pixel + * @return + * true if the transform is possible + */ + public boolean init(IntMatrix m, int foregroundValue) { + init(m); + + for (int i = 0; i < m.size; i++) { + matrix.values[i] = m.values[i] == foregroundValue ? inf : 0; + } + + return isTransformPossible(); + } + + /** + * Initialize transform with an short matrix. + * + * @param m + * An short matrix + * @param foregroundValue + * The value of a foreground pixel + * @return + * true if the transform is possible + */ + public boolean init(ShortMatrix m, short foregroundValue) { + init(m); + + for (int i = 0; i < m.size; i++) { + matrix.values[i] = m.values[i] == foregroundValue ? inf : 0; + } + + return isTransformPossible(); + } + + /** + * Initialize transform with an byte matrix. + * + * @param m + * An byte matrix + * @param foregroundValue + * The value of a foreground pixel + * @return + * true if the transform is possible + */ + public boolean init(ByteMatrix m, byte foregroundValue) { + init(m); + + for (int i = 0; i < m.size; i++) { + matrix.values[i] = m.values[i] == foregroundValue ? inf : 0; + } + + return isTransformPossible(); + } + + /** + * Initialize transform with an long matrix. + * + * @param m + * An long matrix + * @param foregroundValue + * The value of a foreground pixel + * @return + * true if the transform is possible + */ + public boolean init(LongMatrix m, long foregroundValue) { + init(m); + + for (int i = 0; i < m.size; i++) { + matrix.values[i] = m.values[i] == foregroundValue ? inf : 0; + } + + return isTransformPossible(); + } + + /** + * Initialize transform with an double matrix. + * + * @param m + * An double matrix + * @param foregroundValue + * The value of a foreground pixel + * @return + * true if the transform is possible + */ + public boolean init(DoubleMatrix m, double foregroundValue) { + init(m); + + for (int i = 0; i < m.size; i++) { + matrix.values[i] = m.values[i] == foregroundValue ? inf : 0; + } + + return isTransformPossible(); + } + + /** + * Initialize transform with an float matrix. + * + * @param m + * An float matrix + * @param foregroundValue + * The value of a foreground pixel + * @return + * true if the transform is possible + */ + public boolean init(FloatMatrix m, float foregroundValue) { + init(m); + + for (int i = 0; i < m.size; i++) { + matrix.values[i] = m.values[i] == foregroundValue ? inf : 0; + } + + return isTransformPossible(); + } + + /** + * Initialize transform with an arbitrary matrix. + * + * @param m + * A matrix + * @param foregroundValue + * The value of a foreground pixel + * @return + * true if the transform is possible + */ + public boolean init(Matrix m, Number foregroundValue) { + init(m); + + double fgv = foregroundValue.doubleValue(); + for (int i = 0; i < m.size; i++) { + + matrix.values[i] = m.valueAt(i).doubleValue() == fgv ? inf : 0; + } + + return isTransformPossible(); + } + + /** + * Performs the column transform + */ + private final void transformCols() { + + for (int j = 0; j < matrix.cols; j++) { + + // Forward + for (int i = 1, b = 1; i < matrix.rows; i++) { + int idx = i * matrix.cols + j; + + if (matrix.values[idx] > matrix.values[idx-matrix.cols]) { + matrix.values[idx] = matrix.values[idx-matrix.cols] + b; + b += 2; + } else { + b = 1; + } + } + + // Backward + for (int i = matrix.rows - 2, b = 1; i >= 0; i--) { + int idx = i * matrix.cols + j; + + if (matrix.values[idx] > matrix.values[idx+matrix.cols] + b) { + matrix.values[idx] = matrix.values[idx+matrix.cols] + b; + b += 2; + } else { + b = 1; + } + } + } + } + + /** + * Meijsters f function + */ + private static int f(int x, int i, int pixel) { + return (x - i)*(x - i) + pixel; + } + + /** + * Performs the row transform + */ + private final void transformRows() { + // Meijster row transform + + int[] s = new int[matrix.cols]; + int[] t = new int[matrix.cols]; + int[] r = new int[matrix.cols]; + + for (int i = 0; i < matrix.rows; i++) { + int q = s[0] = t[0] = 0; + int offset = i * matrix.cols; + + for (int u = 1; u < matrix.cols; ++u) { + int im_r_u = matrix.values[offset + u]; + + while (q != -1 && + f(t[q], s[q], matrix.values[offset + s[q]]) > + f(t[q], u, im_r_u)) { + --q; + } + + if (q == -1) { + q = 0; + s[0] = u; + } else { + int w = 1 + ((u * u - (s[q] * s[q]) + + matrix.values[offset + u] - matrix.values[offset + s[q]]) + / (2 * (u - s[q]))); + if (w < matrix.cols) { + ++q; + s[q] = u; + t[q] = w; + } + } + } + + System.arraycopy(matrix.values, offset, r, 0, matrix.cols); + + for (int u = matrix.cols - 1; u != -1; --u) { + matrix.values[offset + u] = f(u, s[q], r[s[q]]); + + if (u == t[q]) { + --q; + } + } + } + } + + /** + * Carries out the transform if it has not already been completed + */ + private void squareTransform() { + if (matrix == null) { + throw new IllegalStateException("transform object not initialized"); + } + + if (!done) { + if (matrix.rows > 0 && matrix.cols > 0) { + transformCols(); + transformRows(); + } + done = true; + } + } + + /** + * Compute the square euclidean distance transform and return the result as + * a flattened integer array of square distance values, that has a size of + * rows * columns. + * + * @return flat array of square distance values. + */ + public IntMatrix computeSquareTransform() { + squareTransform(); + return matrix.clone(); + } + + /** + * Compute the euclidean distance transform and return the result as a + * flattened array of double precision floating point values. The returned + * array has a dimension of rows * columns. + * + * @return flattened array of euclidean distance values. + */ + public DoubleMatrix computeTransform() { + squareTransform(); + + DoubleMatrix result = new DoubleMatrix(matrix.rows, matrix.cols); + for (int i = 0; i < matrix.size; i++) { + result.values[i] = Math.sqrt(matrix.values[i]); + } + + return result; + } + + /** + * Compute the euclidean distance transform and return the result as a + * flattened array of single precision floating point values. The returned + * array has a dimension of rows * columns. + * + * @return flattened array of euclidean distance values. + */ + public FloatMatrix computeTransformFloat() { + squareTransform(); + + FloatMatrix result = new FloatMatrix(matrix.rows, matrix.cols); + for (int i = 0; i < matrix.size; i++) { + result.values[i] = (float) Math.sqrt(matrix.values[i]); + } + + return result; + } + + // Some test code + public static void main(String[] args) { + + // Create rectangular mask + int[][] pixels = new int[11][11]; + for (int i = 0; i < pixels.length; i++) { + for (int j = 0; j < pixels[i].length; j++) { + pixels[i][j] = 0; + } + } + pixels[5][5] = 1; + + // Print mask + System.out.println("Pixels: "); + for (int i = 0; i < pixels.length; i++) { + for (int j = 0; j < pixels[i].length; j++) { + System.out.printf("%3d", pixels[i][j]); + System.out.print(' '); + } + System.out.println(); + } + + // Transform + DistanceTransform dt = new DistanceTransform(); + dt.init(new IntMatrix(pixels), 0); + DoubleMatrix result = dt.computeTransform(); + + // Print transform + System.out.println("Result: "); + for (int i = 0; i < result.rows; i++) { + for (int j = 0; j < result.cols; j++) { + System.out.printf("%4.2f", result.doubleAt(i, j)); + System.out.print(' '); + } + System.out.println(); + } + } +} diff --git a/Annotation/src/ie/dcu/image/gray/GrayConvolve.class b/Annotation/src/ie/dcu/image/gray/GrayConvolve.class new file mode 100644 index 0000000..961d5eb Binary files /dev/null and b/Annotation/src/ie/dcu/image/gray/GrayConvolve.class differ diff --git a/Annotation/src/ie/dcu/image/gray/GrayConvolve.java b/Annotation/src/ie/dcu/image/gray/GrayConvolve.java new file mode 100644 index 0000000..fa1c418 --- /dev/null +++ b/Annotation/src/ie/dcu/image/gray/GrayConvolve.java @@ -0,0 +1,37 @@ +package ie.dcu.image.gray; + +import ie.dcu.matrix.DoubleMatrix; + +public class GrayConvolve { + + public static DoubleMatrix convolve( + DoubleMatrix image, DoubleMatrix filter) + { + DoubleMatrix result = new DoubleMatrix(image.rows, image.cols); + + for (int i = 0; i < image.rows; i++) { + for (int j = 0; j < image.cols; j++) { + double value = 0.0; + + for (int ii = 0; ii < filter.rows; ii++) { + int i1 = i - (filter.rows >> 1) + ii; + + if (image.hasRow(i1)) { + for (int jj = 0; jj < filter.cols; jj++) { + int j1 = j - (filter.cols >> 1) + jj; + + if (image.hasCol(j1)) { + double filterValue = filter.doubleAt(ii, jj); + value += image.doubleAt(i1, j1) * filterValue; + } + } + } + } + + result.setDoubleAt(i, j, value); + } + } + + return result; + } +} diff --git a/Annotation/src/ie/dcu/image/gray/GrayImageOp.class b/Annotation/src/ie/dcu/image/gray/GrayImageOp.class new file mode 100644 index 0000000..c134c67 Binary files /dev/null and b/Annotation/src/ie/dcu/image/gray/GrayImageOp.class differ diff --git a/Annotation/src/ie/dcu/image/gray/GrayImageOp.java b/Annotation/src/ie/dcu/image/gray/GrayImageOp.java new file mode 100644 index 0000000..86cf4c5 --- /dev/null +++ b/Annotation/src/ie/dcu/image/gray/GrayImageOp.java @@ -0,0 +1,8 @@ +package ie.dcu.image.gray; + +import ie.dcu.image.ImageOp; + +public interface GrayImageOp extends ImageOp { + + +} diff --git a/Annotation/src/ie/dcu/image/gray/LaplaceFilterOp.class b/Annotation/src/ie/dcu/image/gray/LaplaceFilterOp.class new file mode 100644 index 0000000..3835e87 Binary files /dev/null and b/Annotation/src/ie/dcu/image/gray/LaplaceFilterOp.class differ diff --git a/Annotation/src/ie/dcu/image/gray/LaplaceFilterOp.java b/Annotation/src/ie/dcu/image/gray/LaplaceFilterOp.java new file mode 100644 index 0000000..ff1791a --- /dev/null +++ b/Annotation/src/ie/dcu/image/gray/LaplaceFilterOp.java @@ -0,0 +1,125 @@ +package ie.dcu.image.gray; + +import ie.dcu.image.AbstractImageOp; +import ie.dcu.matrix.*; +import ie.dcu.matrix.Matrix.Type; + +public class LaplaceFilterOp extends AbstractImageOp + implements GrayImageOp +{ + + private boolean clampOutput = true; + private boolean simple = false; + + public static DoubleMatrix rectify(ByteMatrix bm) { + DoubleMatrix im = new DoubleMatrix(bm.rows, bm.cols); + for (int i = 0; i < bm.size; i++) { + im.values[i] = (int) bm.values[i] - (int) Byte.MIN_VALUE; + } + return im; + } + + @Override + protected Matrix processImage(MatrixProvider provider) { + Type type = provider.getDefaultMatrixType(); + + DoubleMatrix input; + if (type != null && type == Type.Byte) { + ByteMatrix matrix = (ByteMatrix) provider.getMatrix(Type.Byte, false); + input = rectify(matrix); + } else { + input = (DoubleMatrix) provider.getMatrix(Type.Double, false); + } + + DoubleMatrix output = simple ? laplace4(input) : laplace8(input); + + + System.out.println("input min = " + input.minValue()); + System.out.println("input max = " + input.maxValue()); + System.out.println("output min = " + output.minValue()); + System.out.println("output max = " + output.maxValue()); + + if (clampOutput) { + + output.clamp(0, Double.MAX_VALUE); + } + + return output; + } + + + public static DoubleMatrix laplace4(DoubleMatrix m) { + DoubleMatrix result = new DoubleMatrix(m.rows, m.cols); + + double n0, n1, n2, n3; + for (int i = 0; i < m.rows; i++) { + + n0 = (i != 0) ? 1 : 0; + n3 = (i != m.rows - 1) ? 1 : 0; + + for (int j = 0; j < m.cols; j++) { + + n1 = (j != 0) ? 1 : 0; + n2 = (j != m.cols-1) ? 1 : 0; + + double value = (n0 + n1 + n2 + n3) * m.doubleAt(i, j); + value -= (n0 != 0) ? m.doubleAt(i-1, j) : 0; + value -= (n1 != 0) ? m.doubleAt(i, j-1) : 0; + value -= (n2 != 0) ? m.doubleAt(i, j+1) : 0; + value -= (n3 != 0) ? m.doubleAt(i+1, j) : 0; + result.setDoubleAt(i, j, value); + } + } + + return result; + } + + public static DoubleMatrix laplace8(DoubleMatrix m) { + DoubleMatrix result = new DoubleMatrix(m.rows, m.cols); + + int a = m.rows - 1; + int b = m.cols - 1; + + double n0, n1, n2, n3, n4, n5, n6, n7; + for (int i = 0; i < m.rows; i++) { + + for (int j = 0; j < m.cols; j++) { + + n0 = (i != 0 && j != 0) ? 1 : 0; + n1 = (i != 0) ? 1 : 0; + n2 = (i != 0 && j != b) ? 1 : 0; + n3 = (j != 0) ? 1 : 0; + n4 = (j != b) ? 1 : 0; + n5 = (i != a && j != 0) ? 1 : 0; + n6 = (i != a) ? 1 : 0; + n7 = (i != a && j != b) ? 1 : 0; + + double w = (n0 + n1 + n2 + n3 + n4 + n5 + n6 + n7); + double v = w * m.doubleAt(i, j); + + v -= (n0 != 0) ? m.doubleAt(i-1, j-1) : 0; + v -= (n1 != 0) ? m.doubleAt(i-1, j ) : 0; + v -= (n2 != 0) ? m.doubleAt(i-1, j+1) : 0; + v -= (n3 != 0) ? m.doubleAt(i , j-1) : 0; + v -= (n4 != 0) ? m.doubleAt(i , j+1) : 0; + v -= (n5 != 0) ? m.doubleAt(i+1, j-1) : 0; + v -= (n6 != 0) ? m.doubleAt(i+1, j ) : 0; + v -= (n7 != 0) ? m.doubleAt(i+1, j+1) : 0; + + result.setDoubleAt(i, j, v); + } + } + + return result; + } + + /* + * (non-Javadoc) + * @see ie.dcu.cdvp.matrix.MatrixProvider#getDefaultMatrixType() + */ + public Type getDefaultMatrixType() { + // we don't know + return null; + } + +} diff --git a/Annotation/src/ie/dcu/matrix/ByteMatrix.class b/Annotation/src/ie/dcu/matrix/ByteMatrix.class new file mode 100644 index 0000000..78909dd Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/ByteMatrix.class differ diff --git a/Annotation/src/ie/dcu/matrix/ByteMatrix.java b/Annotation/src/ie/dcu/matrix/ByteMatrix.java new file mode 100644 index 0000000..885d24a --- /dev/null +++ b/Annotation/src/ie/dcu/matrix/ByteMatrix.java @@ -0,0 +1,431 @@ +/* + * ByteMatrix.java + * + * Copyright (c) 2009 by Kevin McGuinness + */ +package ie.dcu.matrix; + +import ie.dcu.array.Arrays; + +/** + * Two dimensional matrix of byte values. + * + * @author Kevin McGuinness + */ +public class ByteMatrix extends Matrix { + + /** + * Serialization UID. + */ + private static final long serialVersionUID = 6250820249861612603L; + + /** + * Shared empty matrix + */ + private static final ByteMatrix EMPTY_MATRIX = new ByteMatrix(0,0); + + /** + * The byte values of the matrix in row-major order. + */ + public final byte[] values; + + /** + * Construct an uninitialized matrix of the given size. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + */ + public ByteMatrix(int rows, int cols) { + super(Type.Byte, rows, cols); + values = new byte[size]; + } + + /** + * Construct a matrix of the given size with the given values. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + * @param values + * The values to the matrix will have (not copied). + */ + public ByteMatrix(int rows, int cols, byte ... values) { + super(Type.Byte, rows, cols, values.length); + this.values = values; + } + + /** + * Construct a matrix of the given size by copying the values in the + * given two dimensional array. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * @param matrix + * A two dimensional array of byte values. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public ByteMatrix(byte[][] matrix) { + this(rowsIn(matrix), colsIn(matrix)); + flatten(matrix, values); + } + + /** + * Returns the byte value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The byte value at (row, col). + */ + public final byte byteAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Returns the byte value at the index. + * + * @param index + * The index + * @return + * The byte value + */ + public final byte byteAt(Index2D index) { + return values[offsetOf(index)]; + } + + /** + * Set the byte value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The byte value to set. + */ + public final void setByteAt(int row, int col, byte value) { + values[offsetOf(row, col)] = value; + } + + /** + * Set the byte value at the given index. + * + * @param index + * The index. + * @param value + * The byte value to set. + */ + public final void setByteAt(Index2D index, byte value) { + values[offsetOf(index)] = value; + } + + /** + * Returns the byte value at the given offset in the matrix. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The byte value at the given offset. + */ + public final byte byteAt(int offset) { + return values[offset]; + } + + /** + * Set the byte value at the given offset in the matrix. + * + * @param offset + * The matrix offset + * @param value + * The byte value to set. + */ + public final void setByteAt(int offset, byte value) { + values[offset] = value; + } + + /** + * Returns the smallest byte value in the matrix. + * + * @return + * The smallest byte value, or null if the + * matrix is empty. + */ + public final Byte minValue() { + return Arrays.min(values); + } + + /** + * Returns the largest byte value in the matrix. + * + * @return + * The largest byte value, or null if the + * matrix is empty. + */ + public final Byte maxValue() { + return Arrays.max(values); + } + + /** + * Returns a transposed version of the matrix. + */ + public final ByteMatrix transpose() { + ByteMatrix m = new ByteMatrix(cols, rows); + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + m.values[offsetOf(j,i)] = values[offsetOf(i, j)]; + } + } + return m; + } + + /** + * Returns a deep copy of the matrix. + */ + @Override + public ByteMatrix clone() { + return new ByteMatrix(rows, cols, values.clone()); + } + + /** + * Returns true if both matrices are equal in value. + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof ByteMatrix) { + ByteMatrix m = (ByteMatrix) obj; + if (sizeEquals(m)) { + return java.util.Arrays.equals(values, m.values); + } + return false; + } + return super.equals(obj); + } + + /** + * Fills the matrix with the %{primative} value of the given number. + * + * @param number + * The number to fill the matrix with (will be truncated if + * necessary). + * @return + * This matrix. + */ + @Override + public final ByteMatrix fill(Number number) { + java.util.Arrays.fill(values, number.byteValue()); + return this; + } + + /** + * Returns the Byte value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The Byte value at (row, col). + */ + @Override + public final Byte valueAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Set the Number value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int row, int col, Number value) { + values[offsetOf(row, col)] = value.byteValue(); + } + + /** + * Returns the Byte value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The Byte value at the given offset. + */ + @Override + public final Byte valueAt(int offset) { + return values[offset]; + } + + /** + * Set the Number value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int offset, Number value) { + values[offset] = value.byteValue(); + } + + /** + * Returns the matrix values (not copied). + */ + @Override + public final byte[] values() { + return values; + } + + /** + * Returns a shared empty matrix instance. + */ + public static ByteMatrix empty() { + return EMPTY_MATRIX; + } + + /** + * Construct and return an identity matrix with the given number of rows. + * + * @param rows + * The number of rows/columns for the matrix to have. + * @return + * A new identity matrix. + */ + public static ByteMatrix eye(int rows) { + ByteMatrix m = new ByteMatrix(rows, rows); + m.fill(0); + for (int i = 0; i < rows; i++) { + m.setByteAt(i, i, (byte) 1); + } + return m; + } + + /** + * Construct and return an zero matrix with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new zero matrix. + */ + public static ByteMatrix zeros(int rows, int cols) { + ByteMatrix m = new ByteMatrix(rows, rows); + m.fill(0); + return m; + } + + /** + * Construct and return a matrix of ones with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new matrix of ones. + */ + public static ByteMatrix ones(int rows, int cols) { + ByteMatrix m = new ByteMatrix(rows, rows); + m.fill(1); + return m; + } + + /** + * Copy the given two dimensional array of byte values into the given + * array. If the passed array does not contain at enough room for the + * passed matrix, a new array is allocated and returned. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * The copy is performed such that the flattened array is in row major + * order. + * + * @param matrix + * The 2D array of byte values to flatten + * @param array + * The array to copy to (can be null). + * @return + * A flattened version of the matrix. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public static final byte[] flatten(byte[][] matrix, byte[] array) { + int rows = matrix.length; + int cols = matrix.length > 0 ? matrix[0].length : 0; + int size = rows * cols; + + if (array == null || array.length < size) { + array = new byte[size]; + } + + for (int i = 0; i < rows; i++) { + + if (cols != matrix[i].length) { + throw new IllegalArgumentException(); + } + + System.arraycopy(matrix[i], 0, array, cols * i, cols); + } + + return array; + } + + /** + * Returns the number of rows in the given two dimensional array. + * + * @param matrix + * A two dimensional array. + * @return + * The number of rows. + */ + public static final int rowsIn(byte[][] matrix) { + return matrix.length; + } + + /** + * Returns the number of columns in the given two dimensional array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The number of columns. + */ + public static final int colsIn(byte[][] matrix) { + return matrix.length > 0 ? matrix[0].length : 0; + } + + /** + * Returns the total number of elements in the given two dimensional + * array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The total number of elements. + */ + public static final int sizeOf(byte[][] matrix) { + return rowsIn(matrix) * colsIn(matrix); + } +} diff --git a/Annotation/src/ie/dcu/matrix/DoubleMatrix.class b/Annotation/src/ie/dcu/matrix/DoubleMatrix.class new file mode 100644 index 0000000..b001b7a Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/DoubleMatrix.class differ diff --git a/Annotation/src/ie/dcu/matrix/DoubleMatrix.java b/Annotation/src/ie/dcu/matrix/DoubleMatrix.java new file mode 100644 index 0000000..099d550 --- /dev/null +++ b/Annotation/src/ie/dcu/matrix/DoubleMatrix.java @@ -0,0 +1,431 @@ +/* + * DoubleMatrix.java + * + * Copyright (c) 2009 by Kevin McGuinness + */ +package ie.dcu.matrix; + +import ie.dcu.array.Arrays; + +/** + * Two dimensional matrix of double values. + * + * @author Kevin McGuinness + */ +public class DoubleMatrix extends Matrix { + + /** + * Serialization UID. + */ + private static final long serialVersionUID = 3466326831906456667L; + + /** + * Shared empty matrix + */ + private static final DoubleMatrix EMPTY_MATRIX = new DoubleMatrix(0,0); + + /** + * The double values of the matrix in row-major order. + */ + public final double[] values; + + /** + * Construct an uninitialized matrix of the given size. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + */ + public DoubleMatrix(int rows, int cols) { + super(Type.Double, rows, cols); + values = new double[size]; + } + + /** + * Construct a matrix of the given size with the given values. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + * @param values + * The values to the matrix will have (not copied). + */ + public DoubleMatrix(int rows, int cols, double ... values) { + super(Type.Double, rows, cols, values.length); + this.values = values; + } + + /** + * Construct a matrix of the given size by copying the values in the + * given two dimensional array. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * @param matrix + * A two dimensional array of double values. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public DoubleMatrix(double[][] matrix) { + this(rowsIn(matrix), colsIn(matrix)); + flatten(matrix, values); + } + + /** + * Returns the double value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The double value at (row, col). + */ + public final double doubleAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Returns the double value at the index. + * + * @param index + * The index + * @return + * The double value + */ + public final double doubleAt(Index2D index) { + return values[offsetOf(index)]; + } + + /** + * Set the double value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The double value to set. + */ + public final void setDoubleAt(int row, int col, double value) { + values[offsetOf(row, col)] = value; + } + + /** + * Set the double value at the given index. + * + * @param index + * The index. + * @param value + * The double value to set. + */ + public final void setDoubleAt(Index2D index, double value) { + values[offsetOf(index)] = value; + } + + /** + * Returns the double value at the given offset in the matrix. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The double value at the given offset. + */ + public final double doubleAt(int offset) { + return values[offset]; + } + + /** + * Set the double value at the given offset in the matrix. + * + * @param offset + * The matrix offset + * @param value + * The double value to set. + */ + public final void setDoubleAt(int offset, double value) { + values[offset] = value; + } + + /** + * Returns the smallest double value in the matrix. + * + * @return + * The smallest double value, or null if the + * matrix is empty. + */ + public final Double minValue() { + return Arrays.min(values); + } + + /** + * Returns the largest double value in the matrix. + * + * @return + * The largest double value, or null if the + * matrix is empty. + */ + public final Double maxValue() { + return Arrays.max(values); + } + + /** + * Returns a transposed version of the matrix. + */ + public final DoubleMatrix transpose() { + DoubleMatrix m = new DoubleMatrix(cols, rows); + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + m.values[offsetOf(j,i)] = values[offsetOf(i, j)]; + } + } + return m; + } + + /** + * Returns a deep copy of the matrix. + */ + @Override + public DoubleMatrix clone() { + return new DoubleMatrix(rows, cols, values.clone()); + } + + /** + * Returns true if both matrices are equal in value. + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof DoubleMatrix) { + DoubleMatrix m = (DoubleMatrix) obj; + if (sizeEquals(m)) { + return java.util.Arrays.equals(values, m.values); + } + return false; + } + return super.equals(obj); + } + + /** + * Fills the matrix with the %{primative} value of the given number. + * + * @param number + * The number to fill the matrix with (will be truncated if + * necessary). + * @return + * This matrix. + */ + @Override + public final DoubleMatrix fill(Number number) { + java.util.Arrays.fill(values, number.doubleValue()); + return this; + } + + /** + * Returns the Double value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The Double value at (row, col). + */ + @Override + public final Double valueAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Set the Number value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int row, int col, Number value) { + values[offsetOf(row, col)] = value.doubleValue(); + } + + /** + * Returns the Double value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The Double value at the given offset. + */ + @Override + public final Double valueAt(int offset) { + return values[offset]; + } + + /** + * Set the Number value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int offset, Number value) { + values[offset] = value.doubleValue(); + } + + /** + * Returns the matrix values (not copied). + */ + @Override + public final double[] values() { + return values; + } + + /** + * Returns a shared empty matrix instance. + */ + public static DoubleMatrix empty() { + return EMPTY_MATRIX; + } + + /** + * Construct and return an identity matrix with the given number of rows. + * + * @param rows + * The number of rows/columns for the matrix to have. + * @return + * A new identity matrix. + */ + public static DoubleMatrix eye(int rows) { + DoubleMatrix m = new DoubleMatrix(rows, rows); + m.fill(0); + for (int i = 0; i < rows; i++) { + m.setDoubleAt(i, i, (double) 1); + } + return m; + } + + /** + * Construct and return an zero matrix with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new zero matrix. + */ + public static DoubleMatrix zeros(int rows, int cols) { + DoubleMatrix m = new DoubleMatrix(rows, rows); + m.fill(0); + return m; + } + + /** + * Construct and return a matrix of ones with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new matrix of ones. + */ + public static DoubleMatrix ones(int rows, int cols) { + DoubleMatrix m = new DoubleMatrix(rows, rows); + m.fill(1); + return m; + } + + /** + * Copy the given two dimensional array of double values into the given + * array. If the passed array does not contain at enough room for the + * passed matrix, a new array is allocated and returned. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * The copy is performed such that the flattened array is in row major + * order. + * + * @param matrix + * The 2D array of double values to flatten + * @param array + * The array to copy to (can be null). + * @return + * A flattened version of the matrix. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public static final double[] flatten(double[][] matrix, double[] array) { + int rows = matrix.length; + int cols = matrix.length > 0 ? matrix[0].length : 0; + int size = rows * cols; + + if (array == null || array.length < size) { + array = new double[size]; + } + + for (int i = 0; i < rows; i++) { + + if (cols != matrix[i].length) { + throw new IllegalArgumentException(); + } + + System.arraycopy(matrix[i], 0, array, cols * i, cols); + } + + return array; + } + + /** + * Returns the number of rows in the given two dimensional array. + * + * @param matrix + * A two dimensional array. + * @return + * The number of rows. + */ + public static final int rowsIn(double[][] matrix) { + return matrix.length; + } + + /** + * Returns the number of columns in the given two dimensional array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The number of columns. + */ + public static final int colsIn(double[][] matrix) { + return matrix.length > 0 ? matrix[0].length : 0; + } + + /** + * Returns the total number of elements in the given two dimensional + * array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The total number of elements. + */ + public static final int sizeOf(double[][] matrix) { + return rowsIn(matrix) * colsIn(matrix); + } +} diff --git a/Annotation/src/ie/dcu/matrix/FloatMatrix.class b/Annotation/src/ie/dcu/matrix/FloatMatrix.class new file mode 100644 index 0000000..822fbf4 Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/FloatMatrix.class differ diff --git a/Annotation/src/ie/dcu/matrix/FloatMatrix.java b/Annotation/src/ie/dcu/matrix/FloatMatrix.java new file mode 100644 index 0000000..ad4f6ba --- /dev/null +++ b/Annotation/src/ie/dcu/matrix/FloatMatrix.java @@ -0,0 +1,431 @@ +/* + * FloatMatrix.java + * + * Copyright (c) 2009 by Kevin McGuinness + */ +package ie.dcu.matrix; + +import ie.dcu.array.Arrays; + +/** + * Two dimensional matrix of float values. + * + * @author Kevin McGuinness + */ +public class FloatMatrix extends Matrix { + + /** + * Serialization UID. + */ + private static final long serialVersionUID = 8664083529390696723L; + + /** + * Shared empty matrix + */ + private static final FloatMatrix EMPTY_MATRIX = new FloatMatrix(0,0); + + /** + * The float values of the matrix in row-major order. + */ + public final float[] values; + + /** + * Construct an uninitialized matrix of the given size. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + */ + public FloatMatrix(int rows, int cols) { + super(Type.Float, rows, cols); + values = new float[size]; + } + + /** + * Construct a matrix of the given size with the given values. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + * @param values + * The values to the matrix will have (not copied). + */ + public FloatMatrix(int rows, int cols, float ... values) { + super(Type.Float, rows, cols, values.length); + this.values = values; + } + + /** + * Construct a matrix of the given size by copying the values in the + * given two dimensional array. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * @param matrix + * A two dimensional array of float values. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public FloatMatrix(float[][] matrix) { + this(rowsIn(matrix), colsIn(matrix)); + flatten(matrix, values); + } + + /** + * Returns the float value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The float value at (row, col). + */ + public final float floatAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Returns the float value at the index. + * + * @param index + * The index + * @return + * The float value + */ + public final float floatAt(Index2D index) { + return values[offsetOf(index)]; + } + + /** + * Set the float value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The float value to set. + */ + public final void setFloatAt(int row, int col, float value) { + values[offsetOf(row, col)] = value; + } + + /** + * Set the float value at the given index. + * + * @param index + * The index. + * @param value + * The float value to set. + */ + public final void setFloatAt(Index2D index, float value) { + values[offsetOf(index)] = value; + } + + /** + * Returns the float value at the given offset in the matrix. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The float value at the given offset. + */ + public final float floatAt(int offset) { + return values[offset]; + } + + /** + * Set the float value at the given offset in the matrix. + * + * @param offset + * The matrix offset + * @param value + * The float value to set. + */ + public final void setFloatAt(int offset, float value) { + values[offset] = value; + } + + /** + * Returns the smallest float value in the matrix. + * + * @return + * The smallest float value, or null if the + * matrix is empty. + */ + public final Float minValue() { + return Arrays.min(values); + } + + /** + * Returns the largest float value in the matrix. + * + * @return + * The largest float value, or null if the + * matrix is empty. + */ + public final Float maxValue() { + return Arrays.max(values); + } + + /** + * Returns a transposed version of the matrix. + */ + public final FloatMatrix transpose() { + FloatMatrix m = new FloatMatrix(cols, rows); + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + m.values[offsetOf(j,i)] = values[offsetOf(i, j)]; + } + } + return m; + } + + /** + * Returns a deep copy of the matrix. + */ + @Override + public FloatMatrix clone() { + return new FloatMatrix(rows, cols, values.clone()); + } + + /** + * Returns true if both matrices are equal in value. + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof FloatMatrix) { + FloatMatrix m = (FloatMatrix) obj; + if (sizeEquals(m)) { + return java.util.Arrays.equals(values, m.values); + } + return false; + } + return super.equals(obj); + } + + /** + * Fills the matrix with the %{primative} value of the given number. + * + * @param number + * The number to fill the matrix with (will be truncated if + * necessary). + * @return + * This matrix. + */ + @Override + public final FloatMatrix fill(Number number) { + java.util.Arrays.fill(values, number.floatValue()); + return this; + } + + /** + * Returns the Float value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The Float value at (row, col). + */ + @Override + public final Float valueAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Set the Number value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int row, int col, Number value) { + values[offsetOf(row, col)] = value.floatValue(); + } + + /** + * Returns the Float value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The Float value at the given offset. + */ + @Override + public final Float valueAt(int offset) { + return values[offset]; + } + + /** + * Set the Number value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int offset, Number value) { + values[offset] = value.floatValue(); + } + + /** + * Returns the matrix values (not copied). + */ + @Override + public final float[] values() { + return values; + } + + /** + * Returns a shared empty matrix instance. + */ + public static FloatMatrix empty() { + return EMPTY_MATRIX; + } + + /** + * Construct and return an identity matrix with the given number of rows. + * + * @param rows + * The number of rows/columns for the matrix to have. + * @return + * A new identity matrix. + */ + public static FloatMatrix eye(int rows) { + FloatMatrix m = new FloatMatrix(rows, rows); + m.fill(0); + for (int i = 0; i < rows; i++) { + m.setFloatAt(i, i, (float) 1); + } + return m; + } + + /** + * Construct and return an zero matrix with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new zero matrix. + */ + public static FloatMatrix zeros(int rows, int cols) { + FloatMatrix m = new FloatMatrix(rows, rows); + m.fill(0); + return m; + } + + /** + * Construct and return a matrix of ones with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new matrix of ones. + */ + public static FloatMatrix ones(int rows, int cols) { + FloatMatrix m = new FloatMatrix(rows, rows); + m.fill(1); + return m; + } + + /** + * Copy the given two dimensional array of float values into the given + * array. If the passed array does not contain at enough room for the + * passed matrix, a new array is allocated and returned. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * The copy is performed such that the flattened array is in row major + * order. + * + * @param matrix + * The 2D array of float values to flatten + * @param array + * The array to copy to (can be null). + * @return + * A flattened version of the matrix. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public static final float[] flatten(float[][] matrix, float[] array) { + int rows = matrix.length; + int cols = matrix.length > 0 ? matrix[0].length : 0; + int size = rows * cols; + + if (array == null || array.length < size) { + array = new float[size]; + } + + for (int i = 0; i < rows; i++) { + + if (cols != matrix[i].length) { + throw new IllegalArgumentException(); + } + + System.arraycopy(matrix[i], 0, array, cols * i, cols); + } + + return array; + } + + /** + * Returns the number of rows in the given two dimensional array. + * + * @param matrix + * A two dimensional array. + * @return + * The number of rows. + */ + public static final int rowsIn(float[][] matrix) { + return matrix.length; + } + + /** + * Returns the number of columns in the given two dimensional array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The number of columns. + */ + public static final int colsIn(float[][] matrix) { + return matrix.length > 0 ? matrix[0].length : 0; + } + + /** + * Returns the total number of elements in the given two dimensional + * array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The total number of elements. + */ + public static final int sizeOf(float[][] matrix) { + return rowsIn(matrix) * colsIn(matrix); + } +} diff --git a/Annotation/src/ie/dcu/matrix/Index2D.class b/Annotation/src/ie/dcu/matrix/Index2D.class new file mode 100644 index 0000000..58f34ea Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/Index2D.class differ diff --git a/Annotation/src/ie/dcu/matrix/Index2D.java b/Annotation/src/ie/dcu/matrix/Index2D.java new file mode 100644 index 0000000..cb0ef9b --- /dev/null +++ b/Annotation/src/ie/dcu/matrix/Index2D.java @@ -0,0 +1,72 @@ +/* + * Index2D.java + * + * Copyright (c) 2009 by Kevin McGuinness + */ +package ie.dcu.matrix; + +import java.io.Serializable; + +/** + * An immutable class encapsulating a two dimensional index. + * + * @author Kevin McGuinness + */ +public final class Index2D implements Serializable { + + /** + * Serialization UID. + */ + private static final long serialVersionUID = 2722263604670361463L; + + /** + * The row index. + */ + public final int i; + + /** + * The column index. + */ + public final int j; + + /** + * Create an two dimensional index for the given co-ordinates. + * + * @param i + * The row index. + * @param j + * The column index. + */ + public Index2D(int i, int j) { + this.i = i; + this.j = j; + } + + /** + * Returns true if the passed object is an Index2D and both objects are + * have equal values. + */ + @Override + public boolean equals(Object o) { + if (o instanceof Index2D) { + Index2D index = (Index2D) o; + return i == index.i && j == index.j; + } + return false; + } + + /** + * Returns the hash code. + */ + @Override + public int hashCode() { + return (i ^ j); + } + + /** + * Returns a string of the form i,j + */ + public String toString() { + return String.format("%d,%d", i, j); + } +} diff --git a/Annotation/src/ie/dcu/matrix/IntMatrix.class b/Annotation/src/ie/dcu/matrix/IntMatrix.class new file mode 100644 index 0000000..23984ec Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/IntMatrix.class differ diff --git a/Annotation/src/ie/dcu/matrix/IntMatrix.java b/Annotation/src/ie/dcu/matrix/IntMatrix.java new file mode 100644 index 0000000..86f6250 --- /dev/null +++ b/Annotation/src/ie/dcu/matrix/IntMatrix.java @@ -0,0 +1,431 @@ +/* + * IntMatrix.java + * + * Copyright (c) 2009 by Kevin McGuinness + */ +package ie.dcu.matrix; + +import ie.dcu.array.Arrays; + +/** + * Two dimensional matrix of int values. + * + * @author Kevin McGuinness + */ +public class IntMatrix extends Matrix { + + /** + * Serialization UID. + */ + private static final long serialVersionUID = 6142053146188137402L; + + /** + * Shared empty matrix + */ + private static final IntMatrix EMPTY_MATRIX = new IntMatrix(0,0); + + /** + * The int values of the matrix in row-major order. + */ + public final int[] values; + + /** + * Construct an uninitialized matrix of the given size. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + */ + public IntMatrix(int rows, int cols) { + super(Type.Int, rows, cols); + values = new int[size]; + } + + /** + * Construct a matrix of the given size with the given values. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + * @param values + * The values to the matrix will have (not copied). + */ + public IntMatrix(int rows, int cols, int ... values) { + super(Type.Int, rows, cols, values.length); + this.values = values; + } + + /** + * Construct a matrix of the given size by copying the values in the + * given two dimensional array. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * @param matrix + * A two dimensional array of int values. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public IntMatrix(int[][] matrix) { + this(rowsIn(matrix), colsIn(matrix)); + flatten(matrix, values); + } + + /** + * Returns the int value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The int value at (row, col). + */ + public final int intAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Returns the int value at the index. + * + * @param index + * The index + * @return + * The int value + */ + public final int intAt(Index2D index) { + return values[offsetOf(index)]; + } + + /** + * Set the int value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The int value to set. + */ + public final void setIntAt(int row, int col, int value) { + values[offsetOf(row, col)] = value; + } + + /** + * Set the int value at the given index. + * + * @param index + * The index. + * @param value + * The int value to set. + */ + public final void setIntAt(Index2D index, int value) { + values[offsetOf(index)] = value; + } + + /** + * Returns the int value at the given offset in the matrix. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The int value at the given offset. + */ + public final int intAt(int offset) { + return values[offset]; + } + + /** + * Set the int value at the given offset in the matrix. + * + * @param offset + * The matrix offset + * @param value + * The int value to set. + */ + public final void setIntAt(int offset, int value) { + values[offset] = value; + } + + /** + * Returns the smallest int value in the matrix. + * + * @return + * The smallest int value, or null if the + * matrix is empty. + */ + public final Integer minValue() { + return Arrays.min(values); + } + + /** + * Returns the largest int value in the matrix. + * + * @return + * The largest int value, or null if the + * matrix is empty. + */ + public final Integer maxValue() { + return Arrays.max(values); + } + + /** + * Returns a transposed version of the matrix. + */ + public final IntMatrix transpose() { + IntMatrix m = new IntMatrix(cols, rows); + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + m.values[offsetOf(j,i)] = values[offsetOf(i, j)]; + } + } + return m; + } + + /** + * Returns a deep copy of the matrix. + */ + @Override + public IntMatrix clone() { + return new IntMatrix(rows, cols, values.clone()); + } + + /** + * Returns true if both matrices are equal in value. + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof IntMatrix) { + IntMatrix m = (IntMatrix) obj; + if (sizeEquals(m)) { + return java.util.Arrays.equals(values, m.values); + } + return false; + } + return super.equals(obj); + } + + /** + * Fills the matrix with the %{primative} value of the given number. + * + * @param number + * The number to fill the matrix with (will be truncated if + * necessary). + * @return + * This matrix. + */ + @Override + public final IntMatrix fill(Number number) { + java.util.Arrays.fill(values, number.intValue()); + return this; + } + + /** + * Returns the Integer value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The Integer value at (row, col). + */ + @Override + public final Integer valueAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Set the Number value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int row, int col, Number value) { + values[offsetOf(row, col)] = value.intValue(); + } + + /** + * Returns the Integer value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The Integer value at the given offset. + */ + @Override + public final Integer valueAt(int offset) { + return values[offset]; + } + + /** + * Set the Number value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int offset, Number value) { + values[offset] = value.intValue(); + } + + /** + * Returns the matrix values (not copied). + */ + @Override + public final int[] values() { + return values; + } + + /** + * Returns a shared empty matrix instance. + */ + public static IntMatrix empty() { + return EMPTY_MATRIX; + } + + /** + * Construct and return an identity matrix with the given number of rows. + * + * @param rows + * The number of rows/columns for the matrix to have. + * @return + * A new identity matrix. + */ + public static IntMatrix eye(int rows) { + IntMatrix m = new IntMatrix(rows, rows); + m.fill(0); + for (int i = 0; i < rows; i++) { + m.setIntAt(i, i, (int) 1); + } + return m; + } + + /** + * Construct and return an zero matrix with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new zero matrix. + */ + public static IntMatrix zeros(int rows, int cols) { + IntMatrix m = new IntMatrix(rows, rows); + m.fill(0); + return m; + } + + /** + * Construct and return a matrix of ones with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new matrix of ones. + */ + public static IntMatrix ones(int rows, int cols) { + IntMatrix m = new IntMatrix(rows, rows); + m.fill(1); + return m; + } + + /** + * Copy the given two dimensional array of int values into the given + * array. If the passed array does not contain at enough room for the + * passed matrix, a new array is allocated and returned. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * The copy is performed such that the flattened array is in row major + * order. + * + * @param matrix + * The 2D array of int values to flatten + * @param array + * The array to copy to (can be null). + * @return + * A flattened version of the matrix. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public static final int[] flatten(int[][] matrix, int[] array) { + int rows = matrix.length; + int cols = matrix.length > 0 ? matrix[0].length : 0; + int size = rows * cols; + + if (array == null || array.length < size) { + array = new int[size]; + } + + for (int i = 0; i < rows; i++) { + + if (cols != matrix[i].length) { + throw new IllegalArgumentException(); + } + + System.arraycopy(matrix[i], 0, array, cols * i, cols); + } + + return array; + } + + /** + * Returns the number of rows in the given two dimensional array. + * + * @param matrix + * A two dimensional array. + * @return + * The number of rows. + */ + public static final int rowsIn(int[][] matrix) { + return matrix.length; + } + + /** + * Returns the number of columns in the given two dimensional array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The number of columns. + */ + public static final int colsIn(int[][] matrix) { + return matrix.length > 0 ? matrix[0].length : 0; + } + + /** + * Returns the total number of elements in the given two dimensional + * array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The total number of elements. + */ + public static final int sizeOf(int[][] matrix) { + return rowsIn(matrix) * colsIn(matrix); + } +} diff --git a/Annotation/src/ie/dcu/matrix/LongMatrix.class b/Annotation/src/ie/dcu/matrix/LongMatrix.class new file mode 100644 index 0000000..3557ae5 Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/LongMatrix.class differ diff --git a/Annotation/src/ie/dcu/matrix/LongMatrix.java b/Annotation/src/ie/dcu/matrix/LongMatrix.java new file mode 100644 index 0000000..190b06a --- /dev/null +++ b/Annotation/src/ie/dcu/matrix/LongMatrix.java @@ -0,0 +1,431 @@ +/* + * LongMatrix.java + * + * Copyright (c) 2009 by Kevin McGuinness + */ +package ie.dcu.matrix; + +import ie.dcu.array.Arrays; + +/** + * Two dimensional matrix of long values. + * + * @author Kevin McGuinness + */ +public class LongMatrix extends Matrix { + + /** + * Serialization UID. + */ + private static final long serialVersionUID = 8453351009298723791L; + + /** + * Shared empty matrix + */ + private static final LongMatrix EMPTY_MATRIX = new LongMatrix(0,0); + + /** + * The long values of the matrix in row-major order. + */ + public final long[] values; + + /** + * Construct an uninitialized matrix of the given size. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + */ + public LongMatrix(int rows, int cols) { + super(Type.Long, rows, cols); + values = new long[size]; + } + + /** + * Construct a matrix of the given size with the given values. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + * @param values + * The values to the matrix will have (not copied). + */ + public LongMatrix(int rows, int cols, long ... values) { + super(Type.Long, rows, cols, values.length); + this.values = values; + } + + /** + * Construct a matrix of the given size by copying the values in the + * given two dimensional array. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * @param matrix + * A two dimensional array of long values. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public LongMatrix(long[][] matrix) { + this(rowsIn(matrix), colsIn(matrix)); + flatten(matrix, values); + } + + /** + * Returns the long value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The long value at (row, col). + */ + public final long longAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Returns the long value at the index. + * + * @param index + * The index + * @return + * The long value + */ + public final long longAt(Index2D index) { + return values[offsetOf(index)]; + } + + /** + * Set the long value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The long value to set. + */ + public final void setLongAt(int row, int col, long value) { + values[offsetOf(row, col)] = value; + } + + /** + * Set the long value at the given index. + * + * @param index + * The index. + * @param value + * The long value to set. + */ + public final void setLongAt(Index2D index, long value) { + values[offsetOf(index)] = value; + } + + /** + * Returns the long value at the given offset in the matrix. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The long value at the given offset. + */ + public final long longAt(int offset) { + return values[offset]; + } + + /** + * Set the long value at the given offset in the matrix. + * + * @param offset + * The matrix offset + * @param value + * The long value to set. + */ + public final void setLongAt(int offset, long value) { + values[offset] = value; + } + + /** + * Returns the smallest long value in the matrix. + * + * @return + * The smallest long value, or null if the + * matrix is empty. + */ + public final Long minValue() { + return Arrays.min(values); + } + + /** + * Returns the largest long value in the matrix. + * + * @return + * The largest long value, or null if the + * matrix is empty. + */ + public final Long maxValue() { + return Arrays.max(values); + } + + /** + * Returns a transposed version of the matrix. + */ + public final LongMatrix transpose() { + LongMatrix m = new LongMatrix(cols, rows); + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + m.values[offsetOf(j,i)] = values[offsetOf(i, j)]; + } + } + return m; + } + + /** + * Returns a deep copy of the matrix. + */ + @Override + public LongMatrix clone() { + return new LongMatrix(rows, cols, values.clone()); + } + + /** + * Returns true if both matrices are equal in value. + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof LongMatrix) { + LongMatrix m = (LongMatrix) obj; + if (sizeEquals(m)) { + return java.util.Arrays.equals(values, m.values); + } + return false; + } + return super.equals(obj); + } + + /** + * Fills the matrix with the %{primative} value of the given number. + * + * @param number + * The number to fill the matrix with (will be truncated if + * necessary). + * @return + * This matrix. + */ + @Override + public final LongMatrix fill(Number number) { + java.util.Arrays.fill(values, number.longValue()); + return this; + } + + /** + * Returns the Long value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The Long value at (row, col). + */ + @Override + public final Long valueAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Set the Number value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int row, int col, Number value) { + values[offsetOf(row, col)] = value.longValue(); + } + + /** + * Returns the Long value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The Long value at the given offset. + */ + @Override + public final Long valueAt(int offset) { + return values[offset]; + } + + /** + * Set the Number value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int offset, Number value) { + values[offset] = value.longValue(); + } + + /** + * Returns the matrix values (not copied). + */ + @Override + public final long[] values() { + return values; + } + + /** + * Returns a shared empty matrix instance. + */ + public static LongMatrix empty() { + return EMPTY_MATRIX; + } + + /** + * Construct and return an identity matrix with the given number of rows. + * + * @param rows + * The number of rows/columns for the matrix to have. + * @return + * A new identity matrix. + */ + public static LongMatrix eye(int rows) { + LongMatrix m = new LongMatrix(rows, rows); + m.fill(0); + for (int i = 0; i < rows; i++) { + m.setLongAt(i, i, (long) 1); + } + return m; + } + + /** + * Construct and return an zero matrix with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new zero matrix. + */ + public static LongMatrix zeros(int rows, int cols) { + LongMatrix m = new LongMatrix(rows, rows); + m.fill(0); + return m; + } + + /** + * Construct and return a matrix of ones with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new matrix of ones. + */ + public static LongMatrix ones(int rows, int cols) { + LongMatrix m = new LongMatrix(rows, rows); + m.fill(1); + return m; + } + + /** + * Copy the given two dimensional array of long values into the given + * array. If the passed array does not contain at enough room for the + * passed matrix, a new array is allocated and returned. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * The copy is performed such that the flattened array is in row major + * order. + * + * @param matrix + * The 2D array of long values to flatten + * @param array + * The array to copy to (can be null). + * @return + * A flattened version of the matrix. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public static final long[] flatten(long[][] matrix, long[] array) { + int rows = matrix.length; + int cols = matrix.length > 0 ? matrix[0].length : 0; + int size = rows * cols; + + if (array == null || array.length < size) { + array = new long[size]; + } + + for (int i = 0; i < rows; i++) { + + if (cols != matrix[i].length) { + throw new IllegalArgumentException(); + } + + System.arraycopy(matrix[i], 0, array, cols * i, cols); + } + + return array; + } + + /** + * Returns the number of rows in the given two dimensional array. + * + * @param matrix + * A two dimensional array. + * @return + * The number of rows. + */ + public static final int rowsIn(long[][] matrix) { + return matrix.length; + } + + /** + * Returns the number of columns in the given two dimensional array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The number of columns. + */ + public static final int colsIn(long[][] matrix) { + return matrix.length > 0 ? matrix[0].length : 0; + } + + /** + * Returns the total number of elements in the given two dimensional + * array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The total number of elements. + */ + public static final int sizeOf(long[][] matrix) { + return rowsIn(matrix) * colsIn(matrix); + } +} diff --git a/Annotation/src/ie/dcu/matrix/Matrix$1.class b/Annotation/src/ie/dcu/matrix/Matrix$1.class new file mode 100644 index 0000000..c24284f Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/Matrix$1.class differ diff --git a/Annotation/src/ie/dcu/matrix/Matrix$Type.class b/Annotation/src/ie/dcu/matrix/Matrix$Type.class new file mode 100644 index 0000000..c4571be Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/Matrix$Type.class differ diff --git a/Annotation/src/ie/dcu/matrix/Matrix.class b/Annotation/src/ie/dcu/matrix/Matrix.class new file mode 100644 index 0000000..2e3fd38 Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/Matrix.class differ diff --git a/Annotation/src/ie/dcu/matrix/Matrix.java b/Annotation/src/ie/dcu/matrix/Matrix.java new file mode 100644 index 0000000..7ff901f --- /dev/null +++ b/Annotation/src/ie/dcu/matrix/Matrix.java @@ -0,0 +1,768 @@ +/* + * Matrix.java + * + * Copyright (c) 2009 by Kevin McGuinness + * + * TODO: Optimizations in subclasses (toXMatrix) + */ +package ie.dcu.matrix; + +import java.io.*; +import java.util.*; + +import ie.dcu.array.Arrays; + +/** + * Abstract base class for two dimensional matrix types. + * + * @author Kevin McGuinness + */ +public abstract class Matrix implements Cloneable, Serializable, MatrixProvider { + + /** + * Serialization UID. + */ + private static final long serialVersionUID = 7948337494015379755L; + + /** + * Supported matrix types. + */ + public static enum Type { + Byte, + Short, + Int, + Long, + Double, + Float + }; + + /** + * The matrix type. (never null). + */ + public final Type type; + + /** + * The number of rows (height) of the matrix (always >= 0). + */ + public final int rows; + + /** + * The number of rows (width) of the matrix (always >= 0). + */ + public final int cols; + + /** + * The total number of elements matrix (always >= 0). + */ + public final int size; + + /** + * Constructor for subclasses. + * + * @param type + * The matrix type (cannot be null). + * @param rows + * The number or rows in the matrix (must be >= 0). + * @param cols + * The number of columns in the matrix (must be >= 0). + */ + protected Matrix(Type type, int rows, int cols) { + this(type, rows, cols, rows * cols); + } + + /** + * Constructor for subclasses. + * + * The reason this constructor takes a size parameter is to allow + * subclasses to easily ensure the size of a passed array is correct. + * + * @param type + * The matrix type (cannot be null). + * @param rows + * The number or rows in the matrix (must be >= 0). + * @param cols + * The number of columns in the matrix (must be >= 0). + * @param size + * Must equal rows * cols. + */ + protected Matrix(Type type, int rows, int cols, int size) { + if (type == null) { + throw new IllegalArgumentException("type == null"); + } + + if (rows < 0) { + throw new IllegalArgumentException("rows < 0"); + } + + if (cols < 0) { + throw new IllegalArgumentException("cols < 0"); + } + + if (size != rows * cols) { + throw new IllegalArgumentException("size != rows * cols"); + } + + this.type = type; + this.rows = rows; + this.cols = cols; + this.size = size; + } + + /** + * Returns true if the given row index is in range. + * + * @param row + * The row index + */ + public final boolean hasRow(int row) { + return row >= 0 && row < rows; + } + + /** + * Returns true if the given column index is in range. + * + * @param col + * The column index + */ + public final boolean hasCol(int col) { + return col >= 0 && col < cols; + } + + /** + * Returns true if the given row and column index are in range. + * + * @param row + * The row index + * @param col + * The column index + */ + public final boolean hasIndex(int row, int col) { + return row >= 0 && row < rows && col >= 0 && col < cols; + } + + /** + * Returns true if the given two dimensional index is in range. + * + * @param index + * The two dimensional index + */ + public final boolean hasIndex(Index2D index) { + return hasIndex(index.i, index.j); + } + + /** + * Returns true if the given offset is in range. + * + * @param offset + * An absolute offset into the matrix. + */ + public final boolean hasOffset(int offset) { + return offset >= 0 && offset < size; + } + + /** + * Returns true if the given matrix is the same size as the receiver. + * + * @param m + * A matrix of any type. + */ + public final boolean sizeEquals(Matrix m) { + return rows == m.rows && cols == m.cols; + } + + /** + * Returns the width (number of columns) in the matrix. + */ + public final int width() { + return cols; + } + + /** + * Returns the height (number of rows) in the matrix. + */ + public final int height() { + return rows; + } + + /** + * Returns the offset of the given row index. + * + * @param row + * The row index. + */ + public final int offsetOf(int row) { + return row * cols; + } + + /** + * Returns the offset of the given row and column index. + * + * For efficiency this method does not check if the matrix is empty. + * The value col will be returned if it is. + * + * @param row + * The row index. + * @param col + * The column index. + */ + public final int offsetOf(int row, int col) { + return row * cols + col; + } + + /** + * Returns the offset of the given two dimensional index. + * + * For efficiency this method does not check if the matrix is empty. + * The value index.j will be returned if it is. + * + * @param index + * A two dimensional index. + */ + public final int offsetOf(Index2D index) { + return index.i * cols + index.j; + } + + /** + * Returns the two dimensional index of the given offset. + * + * The return value is null if the matrix is empty. + * + * @param offset + * An absolute offset into the matrix. + * @return + * The two dimensional index of the offset. + */ + public final Index2D indexOf(int offset) { + return size != 0 ? new Index2D(offset / cols, offset % cols) : null; + } + + /** + * Returns true of the matrix has zero rows or zero columns. + */ + public final boolean isEmpty() { + return size == 0; + } + + /** + * Returns the Number value at the given row and column. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * A Number value. + */ + public Number valueAt(int row, int col) { + return valueAt(offsetOf(row, col)); + } + + /** + * Returns the Number value at the given two dimensional index. + * + * @param index + * The two dimensional index. + * @return + * A Number value. + */ + public Number valueAt(Index2D index) { + return valueAt(offsetOf(index)); + } + + /** + * Set the Number value at the given row and column. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The Number value to set. + */ + public void setValueAt(int row, int col, Number value) { + setValueAt(offsetOf(row, col), value); + } + + /** + * Set the Number value at the given two dimensional index. + * + * @param index + * The two dimensional index + * @param value + * The Number value to set. + */ + public void setValueAt(Index2D index, Number value) { + setValueAt(offsetOf(index), value); + } + + /** + * Fill the matrix with the given number value. + * + * @param number + * The number value. + * @return This matrix. + */ + public Matrix fill(Number number) { + for (int i = 0; i < size; i++) { + setValueAt(i, number); + } + return this; + } + + /** + * Clamp the matrix values in the given range. + * + * @param min + * The minimum value. + * @param max + * The maximum value. + * @return This matrix. + */ + public Matrix clamp(Number min, Number max) { + Arrays.clamp(values(), min, max); + return this; + } + + /** + * Returns the smallest value in the matrix. + * + * Comparisons are performed in double precision. + * + * @return + * The smallest value, or null if the + * matrix is empty. + */ + public Number minValue() { + Number min = null; + if (!isEmpty()) { + min = valueAt(0); + for (int i = 1; i < size; i++) { + Number value = valueAt(i); + if (value.doubleValue() < min.doubleValue()) { + min = value; + } + } + } + return min; + } + + /** + * Returns the largest value in the matrix. + * + * Comparisons are performed in double precision. + * + * @return + * The largest value, or null if the + * matrix is empty. + */ + public Number maxValue() { + Number max = null; + if (!isEmpty()) { + max = valueAt(0); + for (int i = 1; i < size; i++) { + Number value = valueAt(i); + if (value.doubleValue() > max.doubleValue()) { + max = value; + } + } + } + return max; + } + + /** + * Find the first index containing the given number. If no such index + * exists, null is returned. + * + * Comparison is performed using double precision floats. + * + * @param number + * A Number value. + * @return + * The first index matching the value, or null if none is found. + */ + public Index2D findFirst(Number number) { + double value = number.doubleValue(); + for (int i = 0, k = 0; i < rows; i++) { + for (int j = 0; j < cols; j++, k++) { + if (valueAt(k).doubleValue() == value) { + return new Index2D(i, j); + } + } + } + return null; + } + + /** + * Find the next index containing the given number. If no such index + * exists, null is returned. + * + * Comparison is performed using double precision floats. + * + * @param number + * A Number value. + * @param start + * The index to start at. + * @return + * The first index matching the value, or null if none is found. + */ + public Index2D findNext(Index2D start, Number number) { + double value = number.doubleValue(); + for (int i = start.i; i < rows; i++) { + int k = i * cols; + for (int j = start.j; j < cols; j++, k++) { + + if (valueAt(k).doubleValue() == value) { + return new Index2D(i, j); + } + } + } + return null; + } + + /** + * Find the last index containing the given number. If no such index + * exists, null is returned. + * + * Comparison is performed using double precision floats. + * + * @param number + * A Number value. + * @return + * The last index matching the value, or null if none is found. + */ + public Index2D findLast(Number number) { + double value = number.doubleValue(); + for (int i = rows - 1; i >= 0; i--) { + for (int j = cols - 1; j >= 0; j--) { + if (valueAt(i,j).doubleValue() == value) { + return new Index2D(i, j); + } + } + } + return null; + } + + /** + * Find all indices containing the given number. + * + * The returned list is ordered from first found to last, with the search + * starting at the top left corner of the matrix and proceeding in row major + * order. + * + * Comparison is performed using double precision floats. + * + * @param number + * A Number value. + * @return + * A list of indices. + */ + public List findAll(Number number) { + ArrayList indices = new ArrayList(); + + double value = number.doubleValue(); + for (int i = 0, k = 0; i < rows; i++) { + for (int j = 0; j < cols; j++, k++) { + if (valueAt(k).doubleValue() == value) { + indices.add(new Index2D(i, j)); + } + } + } + + return indices; + } + + /** + * Convert to a ByteMatrix, rounding and truncating if necessary. + * + * @return + * A new ByteMatrix. + */ + public ByteMatrix toByteMatrix() { + return toByteMatrix(null); + } + + /** + * Convert to a ByteMatrix, rounding and truncating if necessary. + * + * If the specified matrix is null or not the same + * size as this matrix, a new matrix is allocated. + * + * @param matrix + * The matrix to copy to. + * @return + * A new ByteMatrix. + */ + public ByteMatrix toByteMatrix(ByteMatrix matrix) { + if (matrix == null || !sizeEquals(matrix)) { + matrix = new ByteMatrix(rows, cols); + } + + Arrays.copy(values(), matrix.values); + return matrix; + } + + /** + * Convert to a ShortMatrix, rounding and truncating if necessary. + * + * @return + * A new ShortMatrix. + */ + public ShortMatrix toShortMatrix() { + return toShortMatrix(null); + } + + /** + * Convert to a ShortMatrix, rounding and truncating if necessary. + * + * If the specified matrix is null or not the same + * size as this matrix, a new matrix is allocated. + * + * @param matrix + * The matrix to copy to. + * @return + * A new ShortMatrix. + */ + public ShortMatrix toShortMatrix(ShortMatrix matrix) { + if (matrix == null || !sizeEquals(matrix)) { + matrix = new ShortMatrix(rows, cols); + } + + Arrays.copy(values(), matrix.values); + return matrix; + } + + /** + * Convert to an IntMatrix, rounding and truncating if necessary. + * + * @return + * A new IntMatrix. + */ + public IntMatrix toIntMatrix() { + return toIntMatrix(null); + } + + /** + * Convert to a IntMatrix, rounding and truncating if necessary. + * + * If the specified matrix is null or not the same + * size as this matrix, a new matrix is allocated. + * + * @param matrix + * The matrix to copy to. + * @return + * A new IntMatrix. + */ + public IntMatrix toIntMatrix(IntMatrix matrix) { + if (matrix == null || !sizeEquals(matrix)) { + matrix = new IntMatrix(rows, cols); + } + + Arrays.copy(values(), matrix.values); + return matrix; + } + + /** + * Convert to a LongMatrix, rounding and truncating if necessary. + * + * @return + * A new LongMatrix. + */ + public LongMatrix toLongMatrix() { + return toLongMatrix(null); + } + + /** + * Convert to a LongMatrix, rounding and truncating if necessary. + * + * If the specified matrix is null or not the same + * size as this matrix, a new matrix is allocated. + * + * @param matrix + * The matrix to copy to. + * @return + * A new LongMatrix. + */ + public LongMatrix toLongMatrix(LongMatrix matrix) { + if (matrix == null || !sizeEquals(matrix)) { + matrix = new LongMatrix(rows, cols); + } + + Arrays.copy(values(), matrix.values); + return matrix; + } + + /** + * Convert to an FloatMatrix, rounding if necessary. + * + * @return + * A new FloatMatrix. + */ + public FloatMatrix toFloatMatrix() { + return toFloatMatrix(null); + } + + /** + * Convert to an FloatMatrix, rounding if necessary. + * + * If the specified matrix is null or not the same + * size as this matrix, a new matrix is allocated. + * + * @param matrix + * The matrix to copy to. + * @return + * A new FloatMatrix. + */ + public FloatMatrix toFloatMatrix(FloatMatrix matrix) { + if (matrix == null || !sizeEquals(matrix)) { + matrix = new FloatMatrix(rows, cols); + } + + Arrays.copy(values(), matrix.values); + return matrix; + } + + /** + * Convert to an DoubleMatrix, rounding if necessary. + * + * @return + * A new DoubleMatrix. + */ + public DoubleMatrix toDoubleMatrix() { + return toDoubleMatrix(null); + } + + /** + * Convert to an DoubleMatrix, rounding if necessary. + * + * If the specified matrix is null or not the same + * size as this matrix, a new matrix is allocated. + * + * @param matrix + * The matrix to copy to. + * @return + * A new DoubleMatrix. + */ + public DoubleMatrix toDoubleMatrix(DoubleMatrix matrix) { + if (matrix == null || !sizeEquals(matrix)) { + matrix = new DoubleMatrix(rows, cols); + } + + Arrays.copy(values(), matrix.values); + return matrix; + } + + /** + * Returns the Number value at the given offset. + * + * @param offset + * An absolute offset into the matrix. + * @return + * The Number value at the offset. + */ + public abstract Number valueAt(int offset); + + /** + * Set the Number value at the given offset. + * + * @param offset + * An absolute offset into the matrix. + * @param value + * The number value to set. + */ + public abstract void setValueAt(int offset, Number value); + + /** + * Returns true of the matrices are the same size and have equal values. + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof Matrix) { + Matrix m = (Matrix) obj; + + if (sizeEquals(m)) { + for (int i = 0; i < size; i++) { + if (!valueAt(i).equals(m.valueAt(i))) { + return false; + } + } + return true; + } + } + + return false; + } + + /** + * Returns the array of matrix values. The return type is dependent + * on the subclass, so Object is given here. + * + * @return The array of values. + */ + public abstract Object values(); + + /** + * Returns a string representation of the matrix. + */ + @Override + public String toString() { + String header = String.format("%dx%d Matrix (%s)", rows, cols, type); + if (rows < 10 && cols < 10) { + // Show the whole matrix + StringBuffer s = new StringBuffer(header); + s.append(" = [\n"); + MatrixFormatter f = new MatrixFormatter(); + f.format(this, s); + s.append(" ]"); + return s.toString(); + } + return header; + } + + /* + * (non-Javadoc) + * @see ie.dcu.cdvp.matrix.MatrixProvider#getDefaultMatrixType() + */ + public Type getDefaultMatrixType() { + return type; + } + + /* + * (non-Javadoc) + * @see ie.dcu.cdvp.matrix.MatrixProvider#getMatrix(boolean) + */ + public Matrix getMatrix(boolean alwaysCopy) { + return getMatrix(null, alwaysCopy); + } + + /* + * (non-Javadoc) + * @see ie.dcu.cdvp.matrix.MatrixProvider#getMatrix(ie.dcu.cdvp.matrix.Matrix.Type, boolean) + */ + public Matrix getMatrix(Type type, boolean alwaysCopy) { + + if (type == null || type == this.type) { + try { + return (alwaysCopy) ? (Matrix) clone() : this; + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } + + switch (type) { + case Byte: + return toByteMatrix(); + case Short: + return toShortMatrix(); + case Int: + return toIntMatrix(); + case Long: + return toLongMatrix(); + case Float: + return toFloatMatrix(); + case Double: + return toDoubleMatrix(); + default: + throw new UnsupportedOperationException(); + } + } +} diff --git a/Annotation/src/ie/dcu/matrix/MatrixFormatter$1.class b/Annotation/src/ie/dcu/matrix/MatrixFormatter$1.class new file mode 100644 index 0000000..6f84be4 Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/MatrixFormatter$1.class differ diff --git a/Annotation/src/ie/dcu/matrix/MatrixFormatter.class b/Annotation/src/ie/dcu/matrix/MatrixFormatter.class new file mode 100644 index 0000000..58eb28c Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/MatrixFormatter.class differ diff --git a/Annotation/src/ie/dcu/matrix/MatrixFormatter.java b/Annotation/src/ie/dcu/matrix/MatrixFormatter.java new file mode 100644 index 0000000..724a770 --- /dev/null +++ b/Annotation/src/ie/dcu/matrix/MatrixFormatter.java @@ -0,0 +1,295 @@ +package ie.dcu.matrix; + +/** + * Handles formating matrices so that all columns are equal width. + * + * @author Kevin McGuinness + */ +public class MatrixFormatter { + + private static final String NaN = "NaN"; + private static final String Inf = "Inf"; + + // Options + private boolean supressSmallValues; + private boolean signAlwaysShown; + private int precision; + + // Internal variables + private boolean expFormat; + private boolean largeExponent; + private String numberFormat; + private String specialFormat; + private int maxStrLen; + + public MatrixFormatter() { + + // Setup defaults + supressSmallValues = false; + signAlwaysShown = false; + precision = 8; + } + + public boolean isSupressSmallValues() { + return supressSmallValues; + } + + public void setSupressSmallValues(boolean value) { + this.supressSmallValues = value; + } + + public boolean isSignAlwaysShown() { + return signAlwaysShown; + } + + public void setSignAlwaysShown(boolean value) { + this.signAlwaysShown = value; + } + + public int getPrecision() { + return precision; + } + + public void setPrecision(int precision) { + if (precision < 0) { + throw new IllegalArgumentException("precision < 0"); + } + this.precision = precision; + } + + public String format(Matrix m) { + return format(m, null).toString(); + } + + public StringBuffer format(Matrix m, StringBuffer s) { + if (s == null) { + s = new StringBuffer(); + } + + if (!m.isEmpty()) { + switch (m.type) { + case Byte: + case Short: + case Int: + case Long: + formatIntegerMatrix(m, s); + break; + default: + formatDecimalMatrix(m, s); + break; + } + } + + return s; + } + + public static String toString(Matrix m) { + return new MatrixFormatter().format(m, null).toString(); + } + + private void formatIntegerMatrix(Matrix m, StringBuffer s) { + analyseIntegerMatrix(m); + + for (int i = 0; i < m.rows; i++) { + for (int j = 0; j < m.cols; j++) { + long value = m.valueAt(i, j).longValue(); + s.append(formatValue(value)); + } + if (i != m.rows - 1) { + s.append('\n'); + } + } + } + + private void formatDecimalMatrix(Matrix m, StringBuffer s) { + analyseDecimalMatrix(m); + + for (int i = 0; i < m.rows; i++) { + for (int j = 0; j < m.cols; j++) { + double v = m.valueAt(i, j).doubleValue(); + s.append(formatValue(v)); + } + if (i != m.rows - 1) { + s.append('\n'); + } + } + } + + private String formatValue(double v) { + if (Double.isNaN(v)) { + return String.format(specialFormat, NaN); + } + + if (Double.isInfinite(v)) { + return String.format(specialFormat, v < 0 ? "-" + Inf : Inf); + } + + StringBuilder s = new StringBuilder(String.format(numberFormat, v)); + + if (largeExponent) { + char sign = s.charAt(s.length()-4); + if (sign == '+' || sign == '-') { + s.insert(s.length()-3, '0'); + } + + } else if (expFormat) { + if (s.charAt(s.length()-4) == '0') { + s.deleteCharAt(s.length()-4); + } + s.insert(0, ' '); + } else if (v != 0) { + while (s.charAt(s.length()-1) == '0' && s.charAt(s.length()-2) != '.') { + s.deleteCharAt(s.length()-1); + s.insert(0, ' '); + } + } + + return s.toString(); + } + + private String formatValue(long value) { + return String.format(numberFormat, value); + } + + private void analyseIntegerMatrix(Matrix m) { + long min = m.maxValue().longValue(); + long max = m.minValue().longValue(); + + int digits = Math.max( + String.valueOf(min).length(), + String.valueOf(max).length()); + + maxStrLen = digits + 1; + if (min >= 0 && signAlwaysShown) { + maxStrLen++; + } + + StringBuilder nfmt = new StringBuilder("%"); + + if (signAlwaysShown) { + nfmt.append('+'); + } + + nfmt.append(maxStrLen); + nfmt.append('d'); + numberFormat = nfmt.toString(); + } + + private void analyseDecimalMatrix(Matrix m) { + expFormat = false; + largeExponent = false; + + boolean hasSpecial = false; + boolean hasNonZero = false; + double minAbsNzVal = Double.MAX_VALUE; + double maxAbsNzVal = Double.MIN_VALUE; + + for (int i = 0; i < m.size; i++) { + double value = m.valueAt(i).doubleValue(); + + if (Double.isNaN(value) || Double.isInfinite(value)) { + hasSpecial = true; + continue; + } + + if (value != 0.0) { + hasNonZero = true; + + double abs = Math.abs(value); + + if (abs < minAbsNzVal) { + minAbsNzVal = abs; + } + + if (abs > maxAbsNzVal) { + maxAbsNzVal = abs; + } + } + } + + if (hasNonZero) { + + if (maxAbsNzVal > 1e8) { + expFormat = true; + } + + if (!supressSmallValues) { + if (minAbsNzVal < 0.0001 || maxAbsNzVal / minAbsNzVal > 1000.0) { + expFormat = true; + } + } + + } else { + + maxAbsNzVal = 0.0; + minAbsNzVal = 0.0; + } + + int truePrecision = precision; + + if (expFormat) { + maxStrLen = 8 + truePrecision; + + if ((minAbsNzVal >= 0 && minAbsNzVal < 1e-99) || maxAbsNzVal > 1e100) { + largeExponent = true; + maxStrLen++; + } + + } else { + + if (hasNonZero) { + String fmt = String.format("%%.%df", precision); + truePrecision = maxDigitCount(fmt, m, precision); + } else { + truePrecision = 0; + } + + truePrecision = Math.min(precision, truePrecision); + int intLength = String.valueOf((long) maxAbsNzVal).length(); + maxStrLen = intLength + truePrecision + 3; + + if (hasSpecial) { + int maxSpecialLen = Math.max(NaN.length(), Inf.length()+1); + maxStrLen = Math.max(maxStrLen, maxSpecialLen); + } + } + + // Compute number format + StringBuffer nfmt = new StringBuffer("%"); + nfmt.append(signAlwaysShown ? "+" : ""); + nfmt.append(maxStrLen); + nfmt.append('.'); + nfmt.append(truePrecision); + nfmt.append(expFormat? 'e' : 'f'); + numberFormat = nfmt.toString(); + + // Compute special format + StringBuffer sfmt = new StringBuffer("%"); + sfmt.append(maxStrLen); + sfmt.append('s'); + specialFormat = sfmt.toString(); + } + + private static int maxDigitCount(String format, Matrix m, int precision) { + int max = 0; + for (int i = 0; i < m.size; i++) { + double v = m.valueAt(i).doubleValue(); + if (!Double.isNaN(v) && !Double.isInfinite(v) && v != 0) { + int count = digitCount(format, v, precision); + if (count > max) { + max = count; + } + } + } + return max; + } + + private static int digitCount(String format, double value, int precision) { + String s = String.format(format, value); + StringBuilder z = new StringBuilder(s); + while (z.length() > 0 && z.charAt(z.length()-1) == '0') { + z.deleteCharAt(z.length()-1); + } + return precision - s.length() + z.length(); + } +} diff --git a/Annotation/src/ie/dcu/matrix/MatrixProvider.class b/Annotation/src/ie/dcu/matrix/MatrixProvider.class new file mode 100644 index 0000000..233f822 Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/MatrixProvider.class differ diff --git a/Annotation/src/ie/dcu/matrix/MatrixProvider.java b/Annotation/src/ie/dcu/matrix/MatrixProvider.java new file mode 100644 index 0000000..774d625 --- /dev/null +++ b/Annotation/src/ie/dcu/matrix/MatrixProvider.java @@ -0,0 +1,41 @@ +package ie.dcu.matrix; + +/** + * Interface for classes that can provide matrices. + * + * @author Kevin McGuinness + */ +public interface MatrixProvider { + + /** + * Returns the default type created by this matrix provider if no type + * is specified when calling getMatrix(). This may be null + * if it is unknown. + * + * @return The default matrix type. + */ + public Matrix.Type getDefaultMatrixType(); + + /** + * Request a matrix from the matrix provider. + * + * @param alwaysCopy + * If true the a copy is always returned, otherwise + * the matrix may or may not be a copy. + * @return A matrix. + */ + public Matrix getMatrix(boolean alwaysCopy); + + /** + * Request a matrix of the given type from the matrix provider. + * + * @param type + * The matrix type. If null then the most convenient + * type for the receiver will be returned. + * @param alwaysCopy + * If true the a copy is always returned, otherwise + * the matrix may or may not be a copy. + * @return A matrix. + */ + public Matrix getMatrix(Matrix.Type type, boolean alwaysCopy); +} diff --git a/Annotation/src/ie/dcu/matrix/ShortMatrix.class b/Annotation/src/ie/dcu/matrix/ShortMatrix.class new file mode 100644 index 0000000..41c3f65 Binary files /dev/null and b/Annotation/src/ie/dcu/matrix/ShortMatrix.class differ diff --git a/Annotation/src/ie/dcu/matrix/ShortMatrix.java b/Annotation/src/ie/dcu/matrix/ShortMatrix.java new file mode 100644 index 0000000..22b0896 --- /dev/null +++ b/Annotation/src/ie/dcu/matrix/ShortMatrix.java @@ -0,0 +1,431 @@ +/* + * ShortMatrix.java + * + * Copyright (c) 2009 by Kevin McGuinness + */ +package ie.dcu.matrix; + +import ie.dcu.array.Arrays; + +/** + * Two dimensional matrix of short values. + * + * @author Kevin McGuinness + */ +public class ShortMatrix extends Matrix { + + /** + * Serialization UID. + */ + private static final long serialVersionUID = 515302276679708530L; + + /** + * Shared empty matrix + */ + private static final ShortMatrix EMPTY_MATRIX = new ShortMatrix(0,0); + + /** + * The short values of the matrix in row-major order. + */ + public final short[] values; + + /** + * Construct an uninitialized matrix of the given size. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + */ + public ShortMatrix(int rows, int cols) { + super(Type.Short, rows, cols); + values = new short[size]; + } + + /** + * Construct a matrix of the given size with the given values. + * + * @param rows + * The number of rows + * @param cols + * The number of columns + * @param values + * The values to the matrix will have (not copied). + */ + public ShortMatrix(int rows, int cols, short ... values) { + super(Type.Short, rows, cols, values.length); + this.values = values; + } + + /** + * Construct a matrix of the given size by copying the values in the + * given two dimensional array. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * @param matrix + * A two dimensional array of short values. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public ShortMatrix(short[][] matrix) { + this(rowsIn(matrix), colsIn(matrix)); + flatten(matrix, values); + } + + /** + * Returns the short value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The short value at (row, col). + */ + public final short shortAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Returns the short value at the index. + * + * @param index + * The index + * @return + * The short value + */ + public final short shortAt(Index2D index) { + return values[offsetOf(index)]; + } + + /** + * Set the short value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The short value to set. + */ + public final void setShortAt(int row, int col, short value) { + values[offsetOf(row, col)] = value; + } + + /** + * Set the short value at the given index. + * + * @param index + * The index. + * @param value + * The short value to set. + */ + public final void setShortAt(Index2D index, short value) { + values[offsetOf(index)] = value; + } + + /** + * Returns the short value at the given offset in the matrix. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The short value at the given offset. + */ + public final short shortAt(int offset) { + return values[offset]; + } + + /** + * Set the short value at the given offset in the matrix. + * + * @param offset + * The matrix offset + * @param value + * The short value to set. + */ + public final void setShortAt(int offset, short value) { + values[offset] = value; + } + + /** + * Returns the smallest short value in the matrix. + * + * @return + * The smallest short value, or null if the + * matrix is empty. + */ + public final Short minValue() { + return Arrays.min(values); + } + + /** + * Returns the largest short value in the matrix. + * + * @return + * The largest short value, or null if the + * matrix is empty. + */ + public final Short maxValue() { + return Arrays.max(values); + } + + /** + * Returns a transposed version of the matrix. + */ + public final ShortMatrix transpose() { + ShortMatrix m = new ShortMatrix(cols, rows); + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + m.values[offsetOf(j,i)] = values[offsetOf(i, j)]; + } + } + return m; + } + + /** + * Returns a deep copy of the matrix. + */ + @Override + public ShortMatrix clone() { + return new ShortMatrix(rows, cols, values.clone()); + } + + /** + * Returns true if both matrices are equal in value. + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof ShortMatrix) { + ShortMatrix m = (ShortMatrix) obj; + if (sizeEquals(m)) { + return java.util.Arrays.equals(values, m.values); + } + return false; + } + return super.equals(obj); + } + + /** + * Fills the matrix with the %{primative} value of the given number. + * + * @param number + * The number to fill the matrix with (will be truncated if + * necessary). + * @return + * This matrix. + */ + @Override + public final ShortMatrix fill(Number number) { + java.util.Arrays.fill(values, number.shortValue()); + return this; + } + + /** + * Returns the Short value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @return + * The Short value at (row, col). + */ + @Override + public final Short valueAt(int row, int col) { + return values[offsetOf(row, col)]; + } + + /** + * Set the Number value at the given row and column index. + * + * @param row + * The row index. + * @param col + * The column index. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int row, int col, Number value) { + values[offsetOf(row, col)] = value.shortValue(); + } + + /** + * Returns the Short value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @return + * The Short value at the given offset. + */ + @Override + public final Short valueAt(int offset) { + return values[offset]; + } + + /** + * Set the Number value at the given matrix offset. + * + * @param offset + * The absolute offset in the matrix. + * @param value + * The Number value to set (will be truncated if necessary). + */ + @Override + public final void setValueAt(int offset, Number value) { + values[offset] = value.shortValue(); + } + + /** + * Returns the matrix values (not copied). + */ + @Override + public final short[] values() { + return values; + } + + /** + * Returns a shared empty matrix instance. + */ + public static ShortMatrix empty() { + return EMPTY_MATRIX; + } + + /** + * Construct and return an identity matrix with the given number of rows. + * + * @param rows + * The number of rows/columns for the matrix to have. + * @return + * A new identity matrix. + */ + public static ShortMatrix eye(int rows) { + ShortMatrix m = new ShortMatrix(rows, rows); + m.fill(0); + for (int i = 0; i < rows; i++) { + m.setShortAt(i, i, (short) 1); + } + return m; + } + + /** + * Construct and return an zero matrix with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new zero matrix. + */ + public static ShortMatrix zeros(int rows, int cols) { + ShortMatrix m = new ShortMatrix(rows, rows); + m.fill(0); + return m; + } + + /** + * Construct and return a matrix of ones with the given number of rows + * and columns. + * + * @param rows + * The number of rows for the matrix to have. + * @param cols + * The number of cols for the matrix to have. + * @return + * A new matrix of ones. + */ + public static ShortMatrix ones(int rows, int cols) { + ShortMatrix m = new ShortMatrix(rows, rows); + m.fill(1); + return m; + } + + /** + * Copy the given two dimensional array of short values into the given + * array. If the passed array does not contain at enough room for the + * passed matrix, a new array is allocated and returned. + * + * The passed two dimensional array must consist of arrays that have + * the same dimension. + * + * The copy is performed such that the flattened array is in row major + * order. + * + * @param matrix + * The 2D array of short values to flatten + * @param array + * The array to copy to (can be null). + * @return + * A flattened version of the matrix. + * @throws IllegalArgumentException + * If the matrix does not contain arrays of the same dimension. + */ + public static final short[] flatten(short[][] matrix, short[] array) { + int rows = matrix.length; + int cols = matrix.length > 0 ? matrix[0].length : 0; + int size = rows * cols; + + if (array == null || array.length < size) { + array = new short[size]; + } + + for (int i = 0; i < rows; i++) { + + if (cols != matrix[i].length) { + throw new IllegalArgumentException(); + } + + System.arraycopy(matrix[i], 0, array, cols * i, cols); + } + + return array; + } + + /** + * Returns the number of rows in the given two dimensional array. + * + * @param matrix + * A two dimensional array. + * @return + * The number of rows. + */ + public static final int rowsIn(short[][] matrix) { + return matrix.length; + } + + /** + * Returns the number of columns in the given two dimensional array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The number of columns. + */ + public static final int colsIn(short[][] matrix) { + return matrix.length > 0 ? matrix[0].length : 0; + } + + /** + * Returns the total number of elements in the given two dimensional + * array. + * + * This method assumes that the arrays in the given matrix all have + * equal lengths. + * + * @param matrix + * A two dimensional array. + * @return + * The total number of elements. + */ + public static final int sizeOf(short[][] matrix) { + return rowsIn(matrix) * colsIn(matrix); + } +} diff --git a/Annotation/src/ie/dcu/plugin/JarResource.class b/Annotation/src/ie/dcu/plugin/JarResource.class new file mode 100644 index 0000000..f7c0fe3 Binary files /dev/null and b/Annotation/src/ie/dcu/plugin/JarResource.class differ diff --git a/Annotation/src/ie/dcu/plugin/Plugin.class b/Annotation/src/ie/dcu/plugin/Plugin.class new file mode 100644 index 0000000..18e551b Binary files /dev/null and b/Annotation/src/ie/dcu/plugin/Plugin.class differ diff --git a/Annotation/src/ie/dcu/plugin/Plugin.java b/Annotation/src/ie/dcu/plugin/Plugin.java new file mode 100644 index 0000000..38d835f --- /dev/null +++ b/Annotation/src/ie/dcu/plugin/Plugin.java @@ -0,0 +1,57 @@ +package ie.dcu.plugin; + +import java.io.File; +import java.net.URLClassLoader; +import java.util.Map; + +public class Plugin { + private final File root; + private final Map metadata; + private final URLClassLoader loader; + + Plugin(File root, Map metadata, URLClassLoader loader) { + this.root = root; + this.metadata = metadata; + this.loader = loader; + } + + public String getName() { + return getMetadata("name"); + } + + public Map getMetadata() { + return metadata; + } + + public String getMetadata(String key) { + return metadata.get(key); + } + + public File getRootFolder() { + return root; + } + + public File getResource(String name) { + return new File(root, name); + } + + public Class loadClass(String name) throws ClassNotFoundException { + return loader.loadClass(name); + } + + public Object loadObject(String name) + throws PluginException + { + try { + Class clazz = loadClass(name); + Object instance = clazz.newInstance(); + return instance; + } catch (ClassNotFoundException e) { + throw new PluginException(e); + } catch (InstantiationException e) { + throw new PluginException(e); + } catch (IllegalAccessException e) { + throw new PluginException(e); + } + } +} diff --git a/Annotation/src/ie/dcu/plugin/PluginClassLoader.class b/Annotation/src/ie/dcu/plugin/PluginClassLoader.class new file mode 100644 index 0000000..f054574 Binary files /dev/null and b/Annotation/src/ie/dcu/plugin/PluginClassLoader.class differ diff --git a/Annotation/src/ie/dcu/plugin/PluginClassLoader.java b/Annotation/src/ie/dcu/plugin/PluginClassLoader.java new file mode 100644 index 0000000..2c29fc5 --- /dev/null +++ b/Annotation/src/ie/dcu/plugin/PluginClassLoader.java @@ -0,0 +1,72 @@ +package ie.dcu.plugin; + +import ie.dcu.util.OsUtils; + +import java.io.File; +import java.net.*; + +public class PluginClassLoader extends URLClassLoader { + + private final File root; + + public PluginClassLoader(File root, URL[] urls, ClassLoader parent) { + super(urls, parent); + this.root = root; + } + + @Override + protected String findLibrary(String libname) { + String path = findLibrary0(libname); + System.out.println("findLibrary: " + libname + " => " + path); + return path; + } + + private String[] getPossibleLibraryNames(String libname) { + if (OsUtils.isLinux64()) { + return new String[] { + libname, + System.mapLibraryName(libname + "64"), + System.mapLibraryName(libname) + }; + } else { + return new String[] { + libname, + System.mapLibraryName(libname) + }; + } + } + + private String findLibrary0(String libname) { + String path; + + // Get a list of potential library names + String[] libnames = getPossibleLibraryNames(libname); + + // Try plugin base folder + if ((path = getPathIfExists(root, libnames)) != null) { + return path; + } + + // Try plugin lib/ subfolder + File libFolder = new File(root, "lib"); + if (libFolder.isDirectory()) { + if ((path = getPathIfExists(libFolder, libnames)) != null) { + return path; + } + } + + // Pass off to the superclass + return super.findLibrary(libname); + } + + private String getPathIfExists(File root, String[] filenames) { + for (String filename : filenames) { + File file = new File(root, filename); + if (file.isFile()) { + return file.getAbsolutePath(); + } + } + return null; + } + +} diff --git a/Annotation/src/ie/dcu/plugin/PluginException.class b/Annotation/src/ie/dcu/plugin/PluginException.class new file mode 100644 index 0000000..1a0f5ce Binary files /dev/null and b/Annotation/src/ie/dcu/plugin/PluginException.class differ diff --git a/Annotation/src/ie/dcu/plugin/PluginException.java b/Annotation/src/ie/dcu/plugin/PluginException.java new file mode 100644 index 0000000..320dc67 --- /dev/null +++ b/Annotation/src/ie/dcu/plugin/PluginException.java @@ -0,0 +1,21 @@ +package ie.dcu.plugin; + +public class PluginException extends Exception { + private static final long serialVersionUID = 1L; + + public PluginException() { + } + + public PluginException(String message) { + super(message); + } + + public PluginException(Throwable cause) { + super(cause); + } + + public PluginException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/Annotation/src/ie/dcu/plugin/PluginLoader$1.class b/Annotation/src/ie/dcu/plugin/PluginLoader$1.class new file mode 100644 index 0000000..5ed0dad Binary files /dev/null and b/Annotation/src/ie/dcu/plugin/PluginLoader$1.class differ diff --git a/Annotation/src/ie/dcu/plugin/PluginLoader$SaxHandler.class b/Annotation/src/ie/dcu/plugin/PluginLoader$SaxHandler.class new file mode 100644 index 0000000..2b0c560 Binary files /dev/null and b/Annotation/src/ie/dcu/plugin/PluginLoader$SaxHandler.class differ diff --git a/Annotation/src/ie/dcu/plugin/PluginLoader.class b/Annotation/src/ie/dcu/plugin/PluginLoader.class new file mode 100644 index 0000000..6acabbd Binary files /dev/null and b/Annotation/src/ie/dcu/plugin/PluginLoader.class differ diff --git a/Annotation/src/ie/dcu/plugin/PluginLoader.java b/Annotation/src/ie/dcu/plugin/PluginLoader.java new file mode 100644 index 0000000..802c437 --- /dev/null +++ b/Annotation/src/ie/dcu/plugin/PluginLoader.java @@ -0,0 +1,159 @@ +package ie.dcu.plugin; + +import java.io.*; +import java.net.*; +import java.util.*; + +import org.xml.sax.*; +import org.xml.sax.helpers.*; + +public class PluginLoader { + public static final String SPECFILE = "plugin.xml"; + + private final File root; + private final Map metadata; + private final List jarFiles; + private URLClassLoader pluginClassLoader; + + public PluginLoader(File root) { + this.root = root; + this.metadata = new HashMap(); + this.jarFiles = new ArrayList(); + + // Extract plugin name + String name = root.getName(); + int idx = name.lastIndexOf('.'); + if (idx > 1) { + name = name.substring(0, idx); + } + metadata.put("name", name); + } + + public File getRootFolder() { + return root; + } + + public File getSpecFile() { + return new File(root, SPECFILE); + } + + public Map getMetadata() { + return metadata; + } + + public String getMetaValue(String key) { + return metadata.get(key); + } + + public Plugin load() throws PluginException { + try { + loadMetadata(); + loadJars(); + return new Plugin(root, metadata, pluginClassLoader); + } catch (SAXException e) { + throw new PluginException(e); + } catch (IOException e) { + throw new PluginException(e); + } + } + + public Class loadClass(String name) throws ClassNotFoundException { + if (pluginClassLoader == null) { + throw new IllegalStateException("load() not called"); + } + return pluginClassLoader.loadClass(name); + } + + private void addJarFile(String path) throws MalformedURLException { + jarFiles.add(new JarResource(root, path)); + } + + private void addMetadata(String key, String value) { + metadata.put(key, value); + } + + private void loadMetadata() throws SAXException, IOException { + BufferedReader reader = new BufferedReader( + new FileReader(getSpecFile())); + try { + InputSource source = new InputSource(reader); + XMLReader xmlreader = XMLReaderFactory.createXMLReader(); + xmlreader.setContentHandler(new SaxHandler()); + xmlreader.parse(source); + } finally { + reader.close(); + } + } + + private void loadJars() { + URL[] jarUrls = new URL[jarFiles.size()]; + int i = 0; + for (JarResource resource : jarFiles) { + jarUrls[i++] = resource.url; + } + ClassLoader parent = getClass().getClassLoader(); + pluginClassLoader = new PluginClassLoader(root, jarUrls, parent); + } + + private class SaxHandler extends DefaultHandler { + private Attributes attrs; + private String elem; + + String getMandatoryAttribute(String name) throws SAXException { + String value = attrs.getValue(name); + if (value == null) { + exception("Missing mandatory attribute '%s'", name); + } + return value; + } + + private void exception(String message, Object ... args) + throws SAXException { + String a = String.format(message, args); + String m = String.format("In element <%s>: %s", elem, a); + throw new SAXException(m); + } + + public void startElement(String uri, String localName, String name, + Attributes attributes) throws SAXException { + elem = name; + attrs = attributes; + parseElem(); + } + + private void parseElem() throws SAXException { + if (elem.equals("meta")) { + String name = getMandatoryAttribute("name"); + String value = getMandatoryAttribute("value"); + addMetadata(name, value); + } else if (elem.equals("jar")) { + String path = getMandatoryAttribute("file"); + try { + addJarFile(path); + } catch (MalformedURLException e) { + throw new SAXException(e); + } + + } else { + // Ignore other elements + } + } + } +} + +class JarResource { + public final File file; + public final URI uri; + public final URL url; + + public JarResource(File root, String path) throws MalformedURLException { + if (new File(path).isAbsolute()) { + this.file = new File(path); + } else { + this.file = new File(root, path); + } + uri = file.toURI(); + url = uri.toURL(); + } +} + diff --git a/Annotation/src/ie/dcu/plugin/PluginManager.class b/Annotation/src/ie/dcu/plugin/PluginManager.class new file mode 100644 index 0000000..c011b36 Binary files /dev/null and b/Annotation/src/ie/dcu/plugin/PluginManager.class differ diff --git a/Annotation/src/ie/dcu/plugin/PluginManager.java b/Annotation/src/ie/dcu/plugin/PluginManager.java new file mode 100644 index 0000000..02991ad --- /dev/null +++ b/Annotation/src/ie/dcu/plugin/PluginManager.java @@ -0,0 +1,78 @@ +package ie.dcu.plugin; + +import java.io.File; +import java.util.*; +import java.util.logging.Logger; + +/** + * I should probably use OSGi or something for this, but I couldn't be + * bothered... + * + * + * @author Kevin McGuinness + */ +public class PluginManager { + private static final Logger log = Logger.getLogger("PluginManager"); + private List searchPath; + private List plugins; + + public PluginManager() { + searchPath = new ArrayList(); + plugins = new ArrayList(); + } + + public List searchPath() { + return searchPath; + } + + public List plugins() { + return Collections.unmodifiableList(plugins); + } + + public void loadPlugins() { + for (String folder : searchPath()) { + loadPluginsFrom(folder); + } + } + + private void loadPluginsFrom(String path) { + log.info("Loading plugins from: " + path); + File file = new File(path); + if (file.isDirectory()) { + loadPluginFromFromFolder(file); + } + } + + private void loadPluginFromFromFolder(File file) { + for (File f : file.listFiles()) { + if (f.isDirectory() && f.getName().endsWith(".plugin")) { + loadPlugin(f); + } + } + } + + public boolean hasPlugin(File pluginFolder) { + String name = pluginFolder.getName(); + for (Plugin p : plugins) { + if (p.getRootFolder().getName().equals(name)) { + return true; + } + } + return false; + } + + private void loadPlugin(File pluginFile) { + if (!hasPlugin(pluginFile)) { + log.info("Loading plugin: " + pluginFile.getName()); + PluginLoader loader = new PluginLoader(pluginFile); + try { + Plugin plugin = loader.load(); + plugins.add(plugin); + } catch (PluginException ex) { + log.severe("Error loading plugin: " + ex.getMessage()); + } + } else { + log.info("Skipping plugin (already loaded): " + pluginFile.getName()); + } + } +} diff --git a/Annotation/src/ie/dcu/segment/SegmentationContext.class b/Annotation/src/ie/dcu/segment/SegmentationContext.class new file mode 100644 index 0000000..96e0b84 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/SegmentationContext.class differ diff --git a/Annotation/src/ie/dcu/segment/SegmentationContext.java b/Annotation/src/ie/dcu/segment/SegmentationContext.java new file mode 100644 index 0000000..229d3c2 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/SegmentationContext.java @@ -0,0 +1,377 @@ +package ie.dcu.segment; + +import ie.dcu.segment.annotate.*; +import ie.dcu.segment.util.*; +import ie.dcu.swt.SwtUtils; +import ie.dcu.util.FileUtils; + +import java.io.*; +import java.util.zip.*; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.Display; + +/** + * Instances of this class manage the context of an interactive segmentation + * task. A segmentation context object is passed to an instance of + * {@link Segmenter} when the segmentation is initialized or updated. The + * segmentation context encapsulates the image being segmented, the current + * segmentation mask, the and the annotations that have been applied to the + * image. + * + * + * @author Kevin McGuinness + */ +public class SegmentationContext { + + /** + * The file extension given to a this object when it is saved on a disk + */ + public static final String EXTENSION = ".ctx"; + + /** + * The original image data + */ + private final ImageData imageData; + + /** + * The file that the context was loaded from or last saved to... this is + * either the original image or a segmentation context file + */ + private File file; + + // lazy create (use getters for these fields) + private AnnotationManager annotations; + private SegmentationMask mask; + private Image image; + private Rectangle bounds; + + /** + * Internal constructor to create an instance of the segmentation context + * from the given image data object and a file object. + * + * @param imageData + * The image data object. + * @param file + * The file from which the image data was loaded. + */ + private SegmentationContext(ImageData imageData, File file) { + this.imageData = imageData; + this.file = file; + } + + /** + * Returns true if the receiver is associated with an existing + * segmentation context file. + */ + public boolean hasContextFile() { + return isContextFile(file); + } + + /** + * Returns the file associated with the receiver. This is either the file + * that the receiver was last stored to, or the image file that was used to + * create the context. + */ + public File getFile() { + return file; + } + + /** + * Get the folder containing the file associated with the receiver. + * + * @see #getFile() + */ + public File getFolder() { + return file.getParentFile(); + } + + /** + * Return an appropriate filename that can be used for saving the receiver. + * + * @see #save(File) + */ + public String getDefaultFilename() { + + String name = file.getName(); + if (hasContextFile()) { + return name; + } + return FileUtils.replaceExtension(name, EXTENSION); + } + + /** + * Returns the current annotations that have been applied to the image. + * + * These annotations can be converted to a raster using the + * {@link AnnotationRasterizer} utility class. + * + * @return An instance of {@link AnnotationManager} + */ + public AnnotationManager getAnnotations() { + if (annotations == null) { + annotations = new AnnotationManager(); + } + return annotations; + } + + /** + * Returns the bounds of the current image and segmentation mask. + * + * @return An SWT Rectangle instance. + */ + public Rectangle getBounds() { + if (bounds == null) { + bounds = new Rectangle(0, 0, imageData.width, imageData.height); + } + return bounds; + } + + /** + * Returns the current segmentation mask. + * + * @return A {@link SegmentationMask} instance. + */ + public SegmentationMask getMask() { + if (mask == null) { + mask = new SegmentationMask(getBounds()); + } + return mask; + } + + /** + * Returns the current image being segmented. This method returns an an SWT + * Image instance, constructing it if it is not already available. The + * {@link #getImageData()} method returns an SWT ImageData representation of + * the current image. + * + * @see #getImageData() + */ + public Image getImage() { + if (image == null || image.isDisposed()) { + image = new Image(Display.getCurrent(), imageData); + } + return image; + } + + /** + * Returns the image data. This is the preferred way of obtaining the image + * pixels since it will never create a new SWT Image instance. The utility + * classes {@link ImageArgbConverter} and {@link ImageByteConverter} can be + * used to convert the image data to a pixel array. + * + * @return An SWT ImageData instance. + */ + public ImageData getImageData() { + return imageData; + } + + /** + * Disposes of the SWT Image instance, if it exists. The Image instance will + * be recreated the next time {@link #getImage()} is called. + */ + public void dispose() { + // Dispose image + if (image != null && !image.isDisposed()) { + image.dispose(); + image = null; + } + } + + /** + * Returns true if the SWT Image managed by the receiver is + * disposed. + */ + public boolean isDisposed() { + if (image != null) { + return image.isDisposed(); + } + return true; + } + + /** + * Create a new segmentation by loading the an image from the given file. + * JPG, PNG, GIF, and BMP images are supported. + * + * @param image + * An image file. + * @return A new segmentation context object. + * @throws IOException + * If the segmentation context cannot be created. + */ + public static SegmentationContext create(File image) throws IOException { + + // Create a new segmentation context + return new SegmentationContext(SwtUtils.loadImageData(image), image); + } + + /** + * Save the receiver to the given file. The context can be loaded again at a + * later stage using the {@link #load(File)} method. + * + *

+ * The saved context is essentially a ZIP file that contains a PNG + * representation of the current image, a PNG representation of the current + * mask file, and a binary representation of the current annotations. + *

+ * + * @param file + * A file. + * @throws IOException + * If there is error saving the receiver to the given file. + */ + public void save(File file) throws IOException { + // Based on zip file format + ZipOutputStream out = new ZipOutputStream(new FileOutputStream(file)); + + try { + // Low (fast) compression.. most of data is PNG compressed anyway + out.setLevel(0); + + // Create an entry for the image + ZipEntry entry = new ZipEntry("image.png"); + + // Start the entry + out.putNextEntry(entry); + + // Store the image + SwtUtils.saveImage(getImageData(), out, SWT.IMAGE_PNG); + + // End the entry + out.closeEntry(); + + // Create an entry for the mask + entry = new ZipEntry("mask.png"); + + // Start the entry + out.putNextEntry(entry); + + // Save the mask + getMask().save(out); + + // End the entry + out.closeEntry(); + + // Create an entry for the annotations + entry = new ZipEntry("markup.dat"); + + // Put next entry + out.putNextEntry(entry); + + // Store the markup + getAnnotations().save(out); + + // close entry + out.closeEntry(); + + } finally { + + // Close + out.close(); + + // Set new filename + this.file = file; + } + } + + /** + * Load a segmentation context object from the disk. + * + * @param file + * A file containing the saved context. + * @return A new segmentation context object. + * @throws IOException + * If there is an error loading the segmentation context file. + */ + public static SegmentationContext load(File file) throws IOException { + ZipInputStream in = new ZipInputStream(new BufferedInputStream( + new FileInputStream(file))); + + ImageData imageData = null; + SegmentationMask mask = null; + AnnotationManager annotations = null; + + try { + ZipEntry entry; + while ((entry = in.getNextEntry()) != null) { + + String name = entry.getName(); + + if (name.equals("image.png")) { + imageData = SwtUtils.loadImageData(in); + + } else if (name.equals("mask.png")) { + mask = SegmentationMask.read(in); + + } else if (name.equals("markup.dat")) { + annotations = new AnnotationManager(); + annotations.load(in); + } + + in.closeEntry(); + } + + } finally { + in.close(); + } + + if (imageData == null) { + throw new IOException("No image found in context file"); + } + + if (mask == null) { + throw new IOException("No mask found in context file"); + } + + if (annotations == null) { + throw new IOException("No annotations found in context file"); + } + + SegmentationContext ctx = new SegmentationContext(imageData, file); + + ctx.mask = mask; + ctx.annotations = annotations; + + return ctx; + } + + /** + * Static method that checks if the given file appears to be a segmentation + * context file. + * + * @param file + * A file. + * @return true if the file appears to be a stored segmentation + * context file. + */ + public static boolean isContextFile(File file) { + if (file != null) { + String name = file.getName().toLowerCase(); + return name.endsWith(EXTENSION); + } + return false; + } + + /** + * Add an annotation listener. This method simply forwards the call to the + * {@link AnnotationManager} class. + * + * @param listener + * An {@link AnnotationListener} instance. + */ + public void addAnnotationListener(AnnotationListener listener) { + getAnnotations().addAnnotationListener(listener); + } + + /** + * Remove an annotation listener. This method simply forwards the call to + * the {@link AnnotationManager} class. + * + * @param listener + * An {@link AnnotationListener} instance. + */ + public void removeAnnotationListener(AnnotationListener listener) { + getAnnotations().removeAnnotationListener(listener); + } +} diff --git a/Annotation/src/ie/dcu/segment/SegmentationMask.class b/Annotation/src/ie/dcu/segment/SegmentationMask.class new file mode 100644 index 0000000..4fd1dc9 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/SegmentationMask.class differ diff --git a/Annotation/src/ie/dcu/segment/SegmentationMask.java b/Annotation/src/ie/dcu/segment/SegmentationMask.java new file mode 100644 index 0000000..6546cc5 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/SegmentationMask.java @@ -0,0 +1,495 @@ +package ie.dcu.segment; + +import ie.dcu.matrix.ByteMatrix; + +import java.io.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; + + +/** + * Class that represents a segmentation mask. + * + * A segmentation mask is a two dimensional matrix of byte values. It is used + * to represents which pixels in an image that are part of the foreground, and + * which are part of the background. + * + * @author Kevin McGuinness + */ +public final class SegmentationMask extends ByteMatrix { + + /** + * Serialization UID + */ + private static final long serialVersionUID = 4110412128756091726L; + + + /** + * Constant value for an unknown pixel. + */ + public static final byte UNKNOWN = 0; + + + /** + * Constant value for a foreground pixel. + */ + public static final byte FOREGROUND = 1; + + + /** + * Constant value of a background pixel. + */ + public static final byte BACKGROUND = 2; + + + /** + * The width of the segmentation mask. + */ + public final int width; + + + /** + * The height of the segmentation mask. + */ + public final int height; + + + /** + * Create a segmentation mask using the specified dimensions. All pixels in + * the mask are initially set to {@link SegmentationMask#UNKNOWN}. + * + * @param width + * The width. + * @param height + * The height. + */ + public SegmentationMask(int width, int height) { + super(height, width); + this.width = width; + this.height = height; + clear(); + } + + + /** + * Create a segmentation mask using the specified dimensions. All pixels in + * the mask are initially set to {@link SegmentationMask#UNKNOWN}. + * + * @param bounds + * The bounds, only the width and height are used. + */ + public SegmentationMask(Rectangle bounds) { + this(bounds.width, bounds.height); + } + + + /** + * Set all pixels in the mask to UNKNOWN. + */ + public final void clear() { + fill(UNKNOWN); + } + + + /** + * Get the offset of pixel (x, y). + * + * @param x + * The x-coordinate. + * @param y + * The y-coordinate. + * @return The offset of pixel at (x, y). + */ + public final int offsetOfPixel(int x, int y) { + return x + y * width; + } + + + /** + * Set the pixel at (x,y) to the given type. The type must be one of: + * + *
    + *
  • {@link SegmentationMask#FOREGROUND}
  • + *
  • {@link SegmentationMask#BACKGROUND}
  • + *
  • {@link SegmentationMask#UNKNOWN}
  • + *
+ * + * Note: This method does not check the type for correctness. + *

+ * + * @param x + * The x-coordinate. + * @param y + * The y-coordinate. + * @param type + * The type. + */ + public final void setPixel(int x, int y, byte type) { + values[x + y * width] = type; + } + + + /** + * Get the type of pixel at position (x, y). + * + * @see SegmentationMask#setPixel(int, int, byte) + * + * @param x + * The x-coordinate. + * @param y + * The y-coordinate. + * @return The type of pixel. + */ + public final byte getPixel(int x, int y) { + return values[x + y * width]; + } + + + /** + * Returns true if the mask doesn't contain any foreground + * or background pixels (All pixels are UNKNOWN) + * + * @return true for an unknown mask. + */ + public final boolean isUnknown() { + for (int i = 0; i < size; i++) { + switch (values[i]) { + case FOREGROUND: + case BACKGROUND: + return false; + } + } + return true; + } + + + /** + * Check if the image contains valid pixel values. + * + * @return true if the image contains valid pixel values. + */ + public final boolean check() { + for (int i = 0; i < size; i++) { + switch (values[i]) { + case UNKNOWN: + case FOREGROUND: + case BACKGROUND: + continue; + default: + return false; + } + } + return true; + } + + + /** + * Get the bounds of the mask. + * + * @return The bounds. + */ + public final Rectangle getBounds() { + return new Rectangle(0, 0, width, height); + } + + + /** + * Returns a string representation of the mask. + */ + public String toString() { + return String.format("SegmentationMask{ %d, %d }", width, height); + } + + + /** + * Save the segmentation mask as a PNG image. + * + * @param file + * The file to save it to. + * @throws IOException + * If the mask cannot be saved for some reason. + */ + public void save(File file) throws IOException { + + // Check if file is a directory + if (file.isDirectory()) { + throw new FileNotFoundException(String.format("%s is a directory", file)); + } + + // Check if we can write to file + if (file.exists()) { + if (!file.canWrite()) { + throw new IOException(String.format("Cannot write to %s", file)); + } + } + + // Check pixels are ok + if (!check()) { + throw new IOException("Image contains invalid pixels, cannot save"); + } + + // Create image loader + ImageLoader loader = new ImageLoader(); + + // Set loader data + loader.data = new ImageData[] { createImageData() }; + + try { + // Save image + loader.save(file.getAbsolutePath(), SWT.IMAGE_PNG); + + } catch (SWTException e) { + // Change unchecked exception to checked one + throw new IOException("SWT Exception: " + e.getMessage()); + } + + // Done + return; + } + + /** + * Store the segmentation mask to an output stream as a PNG image. + * + * @param out + * The output stream. + * @throws IOException + * If an error occurs while saving. + */ + public void save(OutputStream out) throws IOException { + + // Check pixels are ok + if (!check()) { + throw new IOException("Image contains invalid pixels, cannot save"); + } + + // Create image loader + ImageLoader loader = new ImageLoader(); + + // Set loader data + loader.data = new ImageData[] { createImageData() }; + + try { + // Save image + loader.save(out, SWT.IMAGE_PNG); + + } catch (SWTException e) { + // Change unchecked exception to checked one + throw new IOException("SWT Exception: " + e.getMessage()); + } + } + + /** + * Create an SWT ImageData object from the mask. + */ + private ImageData createImageData() { + // Create palette + PaletteData palette = getPalette(); + + // Create 8 bit indexed image + ImageData data = new ImageData(width, height, 8, palette); + + // Blit pixels + for (int y = 0; y < data.height; y++) { + int off1 = y * width; + int off2 = y * data.bytesPerLine; + System.arraycopy(this.values, off1, data.data, off2, width); + } + + return data; + } + + + /** + * Load the mask from a PNG image. + * + * @param file + * The file to load from. + * @throws IOException + * If the mask cannot be loaded for some reason. + */ + public void load(File file) throws IOException { + load(loadImageData(file)); + } + + + /** + * Load the mask from a PNG image. + * + * @param file + * The file to load from. + * @return The mask + * @throws IOException + * If the mask cannot be loaded for some reason. + */ + public static SegmentationMask read(File file) throws IOException { + // Load image data + ImageData data = loadImageData(file); + + // Create compatible mask + SegmentationMask mask = new SegmentationMask(data.width, data.height); + + // Load data into the mask + mask.load(data); + + // Done + return mask; + } + + /** + * Load the mask from a stream containing a PNG image. + * + * @param in + * The stream. + * @return The mask + * @throws IOException + * If the mask cannot be loaded for some reason. + */ + public static SegmentationMask read(InputStream in) throws IOException { + // Load image data + ImageData data = loadImageData(in); + + // Create compatible mask + SegmentationMask mask = new SegmentationMask(data.width, data.height); + + // Load data into the mask + mask.load(data); + + // Done + return mask; + } + + + private static ImageData loadImageData(File file) throws IOException { + // Ensure file exists + if (!file.exists()) { + throw new FileNotFoundException(String.format("%s does not exist", file)); + } + + ImageLoader loader = new ImageLoader(); + + // Load pixels + ImageData[] images; + try { + images = loader.load(file.getAbsolutePath()); + } catch (SWTException e) { + + // Change unchecked exception to checked one + throw new IOException("SWTException: " + e.getMessage()); + } + + // Ensure we have at least one image + if (images.length < 1) { + throw new IOException(String.format("No images found in %s", file)); + } + + // Grab image data + return images[0]; + } + + + private static ImageData loadImageData(InputStream in) throws IOException { + ImageLoader loader = new ImageLoader(); + + // Load pixels + ImageData[] images; + try { + images = loader.load(in); + } catch (SWTException e) { + + // Change unchecked exception to checked one + throw new IOException("SWTException: " + e.getMessage()); + } + + // Ensure we have at least one image + if (images.length < 1) { + throw new IOException(String.format("No images found in stream")); + } + + // Grab image data + return images[0]; + } + + + private void load(ImageData data) throws IOException { + + // Check dimensions + if (width != data.width || height != data.height) { + throw new IOException( + String.format("Invalid dimensions (%d,%d)", data.width, data.height)); + } + + // Check if we have the original format + if (data.palette.isDirect || data.depth != 8) { + + // Okay we definitely don't, do it the slow way + paletteTranslateLoad(data); + + } else { + + // Assume that we do have the original pixels and copy pixels + blitLoad(data); + + // Test our assumption + if (!check()) { + + // We were wrong + paletteTranslateLoad(data); + } + } + + // Check pixels are valid + if (!check()) { + throw new IOException("Image contains invalid pixels"); + } + } + + + private void blitLoad(ImageData data) { + for (int y = 0; y < data.height; y++) { + int off1 = y * data.bytesPerLine; + int off2 = y * width; + System.arraycopy(data.data, off1, this.values, off2, width); + } + } + + + private void paletteTranslateLoad(ImageData data) { + PaletteData palette = getPalette(); + + for (int y = 0; y < height; y++) { + int yoff = y * width; + + for (int x = 0; x < width; x++) { + + // Palette translation + int pel = data.getPixel(x, y); + RGB rgb = data.palette.getRGB(pel); + + // Check for valid rgb, use background pixel on fail + int val = BACKGROUND; + for (int i = 0; i < palette.colors.length; i++) { + if (palette.colors[i].equals(rgb)) { + val = i; + break; + } + } + + // Set + this.values[x+yoff] = (byte) val; + } + } + } + + + private PaletteData getPalette() { + RGB[] colors = new RGB[] { + new RGB(128,128,128), + new RGB(255, 255, 255), + new RGB(0,0,0) + }; + + // Create palette + return new PaletteData(colors); + } +} diff --git a/Annotation/src/ie/dcu/segment/Segmenter.class b/Annotation/src/ie/dcu/segment/Segmenter.class new file mode 100644 index 0000000..16dd641 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/Segmenter.class differ diff --git a/Annotation/src/ie/dcu/segment/Segmenter.java b/Annotation/src/ie/dcu/segment/Segmenter.java new file mode 100644 index 0000000..a29bea7 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/Segmenter.java @@ -0,0 +1,136 @@ +package ie.dcu.segment; + +import ie.dcu.segment.SegmentationContext; +import ie.dcu.segment.annotate.Annotation; +import ie.dcu.segment.options.Option; +import ie.dcu.segment.util.AbstractSegmenter; + +import java.util.Collection; + +/** + * The interface that interactive segmentation algorithms are required to + * implement. + * + * Algorithm implementors can alternatively extend the {@link AbstractSegmenter} + * class. + * + * + * @author Kevin McGuinness + * @version 1.1 + */ +public interface Segmenter { + + /** + * Implementors should return true if the segmentation is + * available on the current platform. If, for example, the segmentation + * algorithm requires native libraries, and there are no such libraries + * compiled for the current platform, this method should return + * false. + * + * @return true if the algorithm is available on this platform, + * false otherwise. + */ + public boolean isAvailable(); + + /** + * Returns the name of the segmentation algorithm. + * + * @return The segmentation algorithm name. (never null). + */ + public String getName(); + + + /** + * Returns a short description of the segmentation algorithm. + * + * @return A description (never null). + */ + public String getDescription(); + + + /** + * Returns the name of the author or vendor. + * + * @return The vendor. + */ + public String getVendor(); + + + /** + * Returns true if the algorithm is "fast". Implementors should + * return true if a call to update typically takes less that a + * second. Otherwise false should be returned. If the speed varies + * or you are unsure, return false. + * + * @return true if the algorithm performs fast updates. + */ + public boolean isFast(); + + + /** + * Get the options (parameters) for the algorithm. This method may return an + * empty collection, but may not return null. + * + * @return A collection of configurable options. + */ + public Collection> getOptions(); + + + /** + * Initialize a new segmentation. This method is provided to + * allow algorithms to initialize any data structures needed + * for segmentation and to perform any pre-segmentation + * necessary. + * + * @param ctx + * The segmentation context. + */ + public void init(SegmentationContext ctx); + + + /** + * Do a full update of the segmentation based on the current context. + * + * @param ctx + * The segmentation context. + */ + public void update(SegmentationContext ctx); + + + /** + * Perform an incremental update when a single annotation is added to the + * context. This method is provided for algorithms that can improve + * performance by only updating based on the last annotation change. + * + * @param ctx + * The segmentation context. + * @param a + * The last annotation. + */ + public void added(SegmentationContext ctx, Annotation a); + + + /** + * Perform an incremental update when a single annotation is removed from the + * context. This method is provided for algorithms that can improve + * performance by only updating based on the last annotation change. + * + * @param ctx + * The segmentation context. + * @param a + * The removed annotation. + */ + public void removed(SegmentationContext ctx, Annotation a); + + + /** + * Perform any operations required before moving on to the next segmentation + * context. This method is provided to allow algorithms to dispose of any + * internal data structures or resources. + * + * @param ctx The segmentation context. + */ + public void finish(SegmentationContext ctx); + + +} diff --git a/Annotation/src/ie/dcu/segment/annotate/Annotation.class b/Annotation/src/ie/dcu/segment/annotate/Annotation.class new file mode 100644 index 0000000..240e257 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/annotate/Annotation.class differ diff --git a/Annotation/src/ie/dcu/segment/annotate/Annotation.java b/Annotation/src/ie/dcu/segment/annotate/Annotation.java new file mode 100644 index 0000000..b2fb899 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/annotate/Annotation.java @@ -0,0 +1,227 @@ +package ie.dcu.segment.annotate; + +import ie.dcu.swt.*; + +import java.util.*; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.*; + +/** + * Class encapsulating a single image annotation. + * + * @author Kevin McGuinness + */ +public class Annotation { + private final AnnotationType type; + private final LinkedList points; + private Rectangle bounds; + private int lineWidth; + + /** + * Create an annotation of the given type. + * + * @param type + * The annotation type. + */ + public Annotation(AnnotationType type) { + this(type, 1); + } + + /** + * Create an annotation of the given type and brush size. + * + * @param type + * The annotation type. + * @param width + * The brush size. + */ + public Annotation(AnnotationType type, int width) { + this (type, width, null); + } + + /** + * Create an annotation of the given type, brush size, and with + * the given initial point. + * + * @param type + * The annotation type. + * @param width + * The brush size. + * @param pt + * The initial point. + */ + public Annotation(AnnotationType type, int width, Point pt) { + assert (type != null); + this.type = type; + points = new LinkedList(); + setLineWidth(width); + + if (pt != null) { + add(pt); + } + } + + + /** + * Set the annotation brush size. + * + * @param width + * The brush size (must be > 0). + */ + public void setLineWidth(int width) { + assert (width > 0); + lineWidth = width; + } + + /** + * Get the annotation brush size. + */ + public int getLineWidth() { + return lineWidth; + } + + /** + * Get the type of annotation. + */ + public AnnotationType getType() { + return type; + } + + /** + * Add a point to the annotation. + * + * @param pt + * A point + */ + public void add(Point pt) { + // Add point + points.add(pt); + + // Expand bounds + Rectangle m = new Rectangle( + pt.x-1, pt.y-1, 3, 3 + ); + + if (bounds == null) { + bounds = SwtUtils.clone(m); + } else { + bounds.add(m); + } + } + + /** + * Returns the last point in the annotation, or null if the + * annotation has no points. + */ + public Point last() { + return points.getLast(); + } + + /** + * Returns the first point in the annotation, or null if the + * annotation has no points. + */ + public Point first() { + return points.getFirst(); + } + + /** + * Render the points onto an {@link ObservableImage} instance. + * + * @param image + * An {@link ObservableImage}. + */ + public void paint(ObservableImage image) { + GC gc = image.beginPaint(); + paint(gc, true); + image.endPaint(getBounds()); + } + + /** + * Render the annotations onto an SWT image instance. + * + * @param image + * An image. + * @param antialias + * Flag indicating whether antialiasing should be done. + */ + public void paint(Image image, boolean antialias) { + GC gc = new GC(image); + paint(gc, antialias); + gc.dispose(); + } + + /** + * Render the annotation onto the graphics context. + * + * @param gc + * A graphics context. + * @param antialias + * Flag indicating whether antialiasing should be done. + */ + public void paint(GC gc, boolean antialias) { + int npoints = points.size(); + if (npoints == 0) return; + + if (antialias) { + gc.setAntialias(SWT.ON); + } + gc.setLineCap(SWT.CAP_ROUND); + gc.setLineJoin(SWT.JOIN_ROUND); + + gc.setLineWidth(lineWidth); + gc.setForeground(type.getColor()); + + Point last = null; + + // Ensure single point or zero length lines are drawn + switch (npoints) { + case 1: + case 2: + Point pt = points.get(0); + last = new Point(pt.x+1, pt.y); + } + + // Draw points + for (Point p : points) { + if (last != null) { + gc.drawLine(last.x, last.y, p.x, p.y); + } + + last = p; + } + } + + /** + * Returns a rectangle that encloses all pixels that this annotation + * represents. If the annotation is empty, returns null. + */ + public Rectangle getBounds() { + if (bounds != null) { + return new Rectangle( + bounds.x - lineWidth / 2, + bounds.y - lineWidth / 2, + bounds.width + lineWidth, + bounds.height + lineWidth + ); + } + + return null; + } + + + /** + * Returns an unmodifiable list of points for this annotation + */ + public List points() { + return Collections.unmodifiableList(points); + } + + /** + * Returns the number of points in this annotation. + */ + public int count() { + return points.size(); + } +} diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationAdapter.class b/Annotation/src/ie/dcu/segment/annotate/AnnotationAdapter.class new file mode 100644 index 0000000..367219d Binary files /dev/null and b/Annotation/src/ie/dcu/segment/annotate/AnnotationAdapter.class differ diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationAdapter.java b/Annotation/src/ie/dcu/segment/annotate/AnnotationAdapter.java new file mode 100644 index 0000000..8ef6cec --- /dev/null +++ b/Annotation/src/ie/dcu/segment/annotate/AnnotationAdapter.java @@ -0,0 +1,46 @@ +package ie.dcu.segment.annotate; + +/** + * Class to simplify implementation of annotation listeners. For use when the + * listener is only interested in changes in the generic sense. + * + * @see AnnotationListener + * @author Kevin McGuinness + */ +public abstract class AnnotationAdapter implements AnnotationListener { + + /** + * Forwards call to {@link #annotationsChanged(AnnotationEvent)} + */ + public void annotationPerformed(AnnotationEvent e) { + annotationsChanged(e); + } + + /** + * Forwards call to {@link #annotationsChanged(AnnotationEvent)} + */ + public void annotationRedone(AnnotationEvent e) { + annotationsChanged(e); + } + + /** + * Forwards call to {@link #annotationsChanged(AnnotationEvent)} + */ + public void annotationUndone(AnnotationEvent e) { + annotationsChanged(e); + } + + /** + * Forwards call to {@link #annotationsChanged(AnnotationEvent)} + */ + public void annotationsCleared(AnnotationEvent e) { + annotationsChanged(e); + } + + /** + * Called when any changes to the annotations occur. + * + * @param e The {@link AnnotationEvent} object. + */ + public abstract void annotationsChanged(AnnotationEvent e); +} diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationEvent$Type.class b/Annotation/src/ie/dcu/segment/annotate/AnnotationEvent$Type.class new file mode 100644 index 0000000..98491b9 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/annotate/AnnotationEvent$Type.class differ diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationEvent.class b/Annotation/src/ie/dcu/segment/annotate/AnnotationEvent.class new file mode 100644 index 0000000..432395e Binary files /dev/null and b/Annotation/src/ie/dcu/segment/annotate/AnnotationEvent.class differ diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationEvent.java b/Annotation/src/ie/dcu/segment/annotate/AnnotationEvent.java new file mode 100644 index 0000000..f189c38 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/annotate/AnnotationEvent.java @@ -0,0 +1,34 @@ +package ie.dcu.segment.annotate; + +/** + * Annotation event class + * + * @see AnnotationListener + * @author Kevin McGuinness + */ +public class AnnotationEvent { + public final AnnotationManager manager; + public final Annotation annotation; + public final Type type; + + + public AnnotationEvent( + AnnotationManager manager, + Annotation annotation, + Type type + ) { + this.manager = manager; + this.annotation = annotation; + this.type = type; + } + + /** + * Event type + */ + public enum Type { + Undone, + Redone, + Added, + Cleared + } +} diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationListener.class b/Annotation/src/ie/dcu/segment/annotate/AnnotationListener.class new file mode 100644 index 0000000..cb1ee74 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/annotate/AnnotationListener.class differ diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationListener.java b/Annotation/src/ie/dcu/segment/annotate/AnnotationListener.java new file mode 100644 index 0000000..7de779b --- /dev/null +++ b/Annotation/src/ie/dcu/segment/annotate/AnnotationListener.java @@ -0,0 +1,14 @@ +package ie.dcu.segment.annotate; + +/** + * Interface for classes interested in annotation events. + * + * @see AnnotationEvent + * @author Kevin McGuinness + */ +public interface AnnotationListener { + public void annotationPerformed(AnnotationEvent e); + public void annotationUndone(AnnotationEvent e); + public void annotationRedone(AnnotationEvent e); + public void annotationsCleared(AnnotationEvent e); +} diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationManager.class b/Annotation/src/ie/dcu/segment/annotate/AnnotationManager.class new file mode 100644 index 0000000..6f7c1e8 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/annotate/AnnotationManager.class differ diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationManager.java b/Annotation/src/ie/dcu/segment/annotate/AnnotationManager.java new file mode 100644 index 0000000..7ea886d --- /dev/null +++ b/Annotation/src/ie/dcu/segment/annotate/AnnotationManager.java @@ -0,0 +1,323 @@ +package ie.dcu.segment.annotate; + +import ie.dcu.swt.ObservableImage; + +import java.io.*; +import java.util.*; + +import org.eclipse.swt.graphics.*; + +/** + * Class that manages a set of image annotations. + * + * @author Kevin McGuinness + */ +public class AnnotationManager { + private static final String FILE_TAG = "Annotations"; + private final LinkedList annotations; + private final LinkedList redos; + private final List listeners; + + public AnnotationManager() { + annotations = new LinkedList(); + redos = new LinkedList(); + listeners = new ArrayList(2); + } + + + public void add(Annotation a) { + annotations.addLast(a); + redos.clear(); + fireAnnotationPerformed(a); + } + + + public boolean canUndo() { + return !annotations.isEmpty(); + } + + + public boolean canRedo() { + return !redos.isEmpty(); + } + + + public void undo() { + if (canUndo()) { + Annotation a = annotations.removeLast(); + redos.addFirst(a); + fireAnnotationUndone(a); + } + } + + + public void redo() { + if (canRedo()) { + Annotation a = redos.removeFirst(); + annotations.addLast(a); + fireAnnotationRedone(a); + } + } + + + public void clear() { + if (annotations.size() > 0) { + annotations.clear(); + redos.clear(); + fireAnnotationsCleared(); + } + } + + + public Annotation getUndoable() { + if (!canUndo()) { + return null; + } + return annotations.getLast(); + } + + + public Annotation getRedoable() { + if (!canRedo()) { + return null; + } + return redos.getFirst(); + } + + + public Annotation last() { + if (!annotations.isEmpty()) { + return annotations.getLast(); + } + return null; + } + + + public List annotations() { + return Collections.unmodifiableList(annotations); + } + + + public int count() { + return annotations.size(); + } + + + public int countForeground() { + int count = 0; + for (Annotation a : annotations) { + if (a.getType() == AnnotationType.Foreground) { + count++; + } + } + return count; + } + + + public int countBackground() { + int count = 0; + for (Annotation a : annotations) { + if (a.getType() == AnnotationType.Background) { + count++; + } + } + return count; + } + + + public boolean hasForegroundAnnotation() { + for (Annotation a : annotations) { + if (a.getType() == AnnotationType.Foreground) { + return true; + } + } + return false; + } + + + public boolean hasBackgroundAnnotation() { + for (Annotation a : annotations) { + if (a.getType() == AnnotationType.Background) { + return true; + } + } + return false; + } + + + public void paint(ObservableImage image) { + for (Annotation a : annotations) { + a.paint(image); + } + } + + + public void paint(GC gc, boolean antialias) { + for (Annotation a : annotations) { + a.paint(gc, antialias); + } + } + + + public void paint(Image image, boolean antialias) { + for (Annotation a : annotations) { + a.paint(image, antialias); + } + } + + + public Rectangle getBounds() { + Rectangle rect = new Rectangle(0,0,0,0); + for (Annotation a : annotations) { + rect.add(a.getBounds()); + } + return rect; + } + + + public void addAnnotationListener(AnnotationListener listener) { + listeners.add(listener); + } + + + public void removeAnnotationListener(AnnotationListener listener) { + listeners.remove(listener); + } + + + private void fireAnnotationsCleared() { + AnnotationEvent e = null; + for (AnnotationListener listener : listeners) { + if (e == null) { + e = new AnnotationEvent(this, null, AnnotationEvent.Type.Cleared); + } + listener.annotationsCleared(e); + } + } + + + private void fireAnnotationPerformed(Annotation a) { + AnnotationEvent e = null; + for (AnnotationListener listener : listeners) { + if (e == null) { + e = new AnnotationEvent(this, a, AnnotationEvent.Type.Added); + } + listener.annotationPerformed(e); + } + } + + + private void fireAnnotationUndone(Annotation a) { + AnnotationEvent e = null; + for (AnnotationListener listener : listeners) { + if (e == null) { + e = new AnnotationEvent(this, a, AnnotationEvent.Type.Undone); + } + listener.annotationUndone(e); + } + } + + + private void fireAnnotationRedone(Annotation a) { + AnnotationEvent e = null; + for (AnnotationListener listener : listeners) { + if (e == null) { + e = new AnnotationEvent(this, a, AnnotationEvent.Type.Redone); + } + listener.annotationRedone(e); + } + } + + + public void save(File file) throws IOException { + FileOutputStream out = new FileOutputStream(file); + + try { + save(out); + } finally { + out.close(); + } + } + + public void save(OutputStream o) throws IOException { + + DataOutputStream out = new DataOutputStream( + new BufferedOutputStream(o)); + + // Write tag and count + out.writeUTF(FILE_TAG); + out.writeInt(annotations.size()); + + for (Annotation a : annotations) { + + // Write parameters + out.writeInt(a.getType().ordinal()); + out.writeInt(a.getLineWidth()); + out.writeInt(a.points().size()); + + // Write points + for (Point p : a.points()) { + out.writeInt(p.x); + out.writeInt(p.y); + } + } + + // Flush + out.flush(); + } + + public void load(File file) throws IOException { + + FileInputStream in = new FileInputStream(file); + + try { + load(in); + } finally { + in.close(); + } + } + + public void load(InputStream is) throws IOException { + + // In case container is being reused, clear old data first + annotations.clear(); + redos.clear(); + + // Create and buffer data input stream + DataInputStream in = new DataInputStream( + new BufferedInputStream(is) + ); + + // Check tag + String tag = in.readUTF(); + if (!tag.equals(FILE_TAG)) { + throw new IOException("Unrecognized file format"); + } + + // Read annotations + int n = in.readInt(); + for (int i = 0; i < n; i++) { + + // Read parameters + int typeid = in.readInt(); + int lineWidth = in.readInt(); + int npoints = in.readInt(); + + + // Create annotation + AnnotationType type = AnnotationType.valueOf(typeid); + Annotation a = new Annotation(type, lineWidth); + + + // Read points + for (int j = 0; j < npoints; j++) { + int x = in.readInt(); + int y = in.readInt(); + a.add(new Point(x, y)); + } + + //Add annotation + add(a); + } + } +} diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationType$1.class b/Annotation/src/ie/dcu/segment/annotate/AnnotationType$1.class new file mode 100644 index 0000000..35f2b63 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/annotate/AnnotationType$1.class differ diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationType.class b/Annotation/src/ie/dcu/segment/annotate/AnnotationType.class new file mode 100644 index 0000000..ae636a4 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/annotate/AnnotationType.class differ diff --git a/Annotation/src/ie/dcu/segment/annotate/AnnotationType.java b/Annotation/src/ie/dcu/segment/annotate/AnnotationType.java new file mode 100644 index 0000000..0eb7b64 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/annotate/AnnotationType.java @@ -0,0 +1,133 @@ +package ie.dcu.segment.annotate; + +import org.eclipse.jface.resource.*; +import org.eclipse.jface.util.*; +import org.eclipse.swt.graphics.*; + +/** + * Annotation type enumeration. + * + * The color of the foreground/background brushes is stored in the JFace + * ColorRegistry using the {@link #key} value to generate the key. If changed + * the {@link #getColor()} method will return the new color. will return the new + * color. + * + * @author Kevin McGuinness + * + */ +public enum AnnotationType implements IPropertyChangeListener { + // Ordinal used for serialization, don't change order + Foreground, + Background; + + + /** + * Default foreground color. + */ + public static final RGB DEFAULT_FOREGROUND = new RGB(255,0,0); + + + /** + * Default background color. + */ + public static final RGB DEFAULT_BACKGROUND = new RGB(0,0,255); + + + /** + * Annotation color registry key. + */ + public final String key; + + + /** + * Annotation brush color. + */ + private Color color; + + + /** + * Initializer + */ + private AnnotationType() { + key = String.format("%s#%s", getClass().getName(), name()); + } + + + /** + * Get the color of the annotation brush. + * + * @return The annotation brush color. + */ + public Color getColor() { + if (color == null) { + + // Get registry + ColorRegistry cr = JFaceResources.getColorRegistry(); + + + // Set default + if (!cr.hasValueFor(key)) { + switch (this) { + case Foreground: + cr.put(key, DEFAULT_FOREGROUND); + break; + default: + cr.put(key, DEFAULT_BACKGROUND); + } + } + + cr.addListener(this); + + // Get color + color = cr.get(key); + } + + return color; + } + + + /** + * Returns the annotation type, inverted. + * + * @return The opposite annotation type. + */ + public AnnotationType invert() { + switch (this) { + case Foreground: + return Background; + case Background: + return Foreground; + } + throw new Error(); + } + + + /** + * Returns the annotation type corresponding to the given ordinal. + * + * @param ordinal + * The ordinal. + * @return The annotation type. + * @throws IllegalArgumentException + * If the given ordinal value is out of range. + */ + public static AnnotationType valueOf(int ordinal) throws IllegalArgumentException { + AnnotationType[] values = values(); + if (ordinal < 0 || ordinal >= values.length) { + throw new IllegalArgumentException("No such ordinal value: " + ordinal); + } + return values[ordinal]; + } + + + /** + * Listen for changes in the color registry + */ + public void propertyChange(PropertyChangeEvent e) { + if (e.getProperty().equals(key)) { + JFaceResources.getColorRegistry().removeListener(this); + // Flag property needs reloading + color = null; + } + } +} diff --git a/Annotation/src/ie/dcu/segment/options/AbstractEditor.class b/Annotation/src/ie/dcu/segment/options/AbstractEditor.class new file mode 100644 index 0000000..1ae9eab Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/AbstractEditor.class differ diff --git a/Annotation/src/ie/dcu/segment/options/AbstractOption.class b/Annotation/src/ie/dcu/segment/options/AbstractOption.class new file mode 100644 index 0000000..0b64157 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/AbstractOption.class differ diff --git a/Annotation/src/ie/dcu/segment/options/AbstractOption.java b/Annotation/src/ie/dcu/segment/options/AbstractOption.java new file mode 100644 index 0000000..da9dd2a --- /dev/null +++ b/Annotation/src/ie/dcu/segment/options/AbstractOption.java @@ -0,0 +1,91 @@ +package ie.dcu.segment.options; + +/** + * Abstract implementation of the {@link Option} interface. + * + * @author Kevin McGuinness + */ +public abstract class AbstractOption implements Option { + private final OptionType type; + private final String name; + private final String description; + private final T defaultValue; + private T value; + + + protected AbstractOption( + OptionType type, String name, String description, T defaultValue) { + + // Preconditions + assert (type != null); + assert (name != null); + assert (description != null); + assert (defaultValue != null); + + // Assign + this.type = type; + this.name = name; + this.description = description; + this.defaultValue = defaultValue; + this.value = defaultValue; + } + + + public OptionType getType() { + return type; + } + + + public String getName() { + return name; + } + + + public String getDescription() { + return description; + } + + + public T getDefaultValue() { + return defaultValue; + } + + + public T getValue() { + return value; + } + + + public void setValue(Object value) { + if (value == null) { + this.value = defaultValue; + } else { + Conversion conv = convert(value); + if (conv.isOk()) { + this.value = conv.getResult(); + } else { + this.value = defaultValue; + } + } + } + + + public T[] values() { + return null; + } + + + protected Conversion valid(T result) { + return new Conversion(result, null); + } + + + protected Conversion invalid(String message) { + return new Conversion(null, message); + } + + + protected Conversion invalid(String format, Object... args) { + return new Conversion(null, String.format(format, args)); + } +} diff --git a/Annotation/src/ie/dcu/segment/options/ComboEditor.class b/Annotation/src/ie/dcu/segment/options/ComboEditor.class new file mode 100644 index 0000000..513d573 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/ComboEditor.class differ diff --git a/Annotation/src/ie/dcu/segment/options/Conversion.class b/Annotation/src/ie/dcu/segment/options/Conversion.class new file mode 100644 index 0000000..48e0a23 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/Conversion.class differ diff --git a/Annotation/src/ie/dcu/segment/options/Conversion.java b/Annotation/src/ie/dcu/segment/options/Conversion.java new file mode 100644 index 0000000..468f167 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/options/Conversion.java @@ -0,0 +1,54 @@ +package ie.dcu.segment.options; + +/** + * The result of an attempted conversion. + * + * @author Kevin McGuinness + */ +public class Conversion { + private final String message; + private final T result; + + /** + * Create a conversion object with the given message and result. The message + * should be null if the conversion was valid. + * + * @param result + * The result, or null. + * @param message + * A message, or null. + */ + public Conversion(T result, String message) { + this.message = message; + this.result = result; + } + + /** + * Returns true of the conversion went OK. + */ + public boolean isOk() { + return message == null; + } + + /** + * Returns an error message if the conversion failed. + */ + public String getMessage() { + return message; + } + + /** + * Returns the result of the conversion if it succeeded. + */ + public T getResult() { + return result; + } + + public String toString() { + if (isOk()) { + return String.format("Conversion [ value = %s ]", result); + } else { + return String.format("Conversion [ error = %s ]", message); + } + } +} diff --git a/Annotation/src/ie/dcu/segment/options/ConversionListener.class b/Annotation/src/ie/dcu/segment/options/ConversionListener.class new file mode 100644 index 0000000..31ff855 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/ConversionListener.class differ diff --git a/Annotation/src/ie/dcu/segment/options/DecimalOption.class b/Annotation/src/ie/dcu/segment/options/DecimalOption.class new file mode 100644 index 0000000..c41c985 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/DecimalOption.class differ diff --git a/Annotation/src/ie/dcu/segment/options/DecimalOption.java b/Annotation/src/ie/dcu/segment/options/DecimalOption.java new file mode 100644 index 0000000..649e6cc --- /dev/null +++ b/Annotation/src/ie/dcu/segment/options/DecimalOption.java @@ -0,0 +1,76 @@ +package ie.dcu.segment.options; + +/** + * A decimal (floating point) segmentation algorithm parameter. + * + * @author Kevin McGuinness + */ +public class DecimalOption extends AbstractOption { + private final double min; + private final double max; + + + /** + * Create a decimal option with the given name, description, and default + * value. + * + * @param name + * The option name + * @param description + * A description of the option + * @param def + * The default value for the option + */ + public DecimalOption(String name, String description, double def) { + this(name, description, def, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); + } + + /** + * Create a decimal option with the given name, description, default + * value, minimum allowable value, and maximum allowable value. + * + * @param name + * The option name + * @param description + * A description of the option + * @param def + * The default value for the option + * @param min + * The minimum allowable value for the option + * @param max + * The maximum allowable value for the option + */ + public DecimalOption(String name, String description, double def, double min, double max) { + super(OptionType.Decimal, name, description, def); + this.min = min; + this.max = max; + } + + public Conversion convert(Object value) { + if (value instanceof Double) { + return valid((Double) value); + } else if (value != null) { + try { + return checkRange(new Double(value.toString().trim())); + } catch (NumberFormatException e) { + // Invalid + String mesg = e.getLocalizedMessage(); + return invalid("%s is not an decimal number: %s", getName(), mesg); + } + } + return invalid("value is null"); + } + + + private Conversion checkRange(double val) { + if (val >= min && val <= max) { + // OK + return valid(val); + + } + + // Out of range + String format = "%s must be in ther range (%f, %f), value is %f"; + return invalid(format, getName(), min, max, val); + } +} diff --git a/Annotation/src/ie/dcu/segment/options/EnumOption.class b/Annotation/src/ie/dcu/segment/options/EnumOption.class new file mode 100644 index 0000000..5462be7 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/EnumOption.class differ diff --git a/Annotation/src/ie/dcu/segment/options/EnumOption.java b/Annotation/src/ie/dcu/segment/options/EnumOption.java new file mode 100644 index 0000000..11ced43 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/options/EnumOption.java @@ -0,0 +1,65 @@ +package ie.dcu.segment.options; + +/** + * A segmentation algorithm parameter that can assume one of a set of predefined + * values. + * + * @author Kevin McGuinness + */ +public class EnumOption> extends AbstractOption { + private Class clazz; + + + /** + * Create an enum option. + * + * @param clazz + * The class of the enum. + * @param name + * The option name. + * @param description + * The option description. + * @param def + * The default value. + */ + public EnumOption(Class clazz, String name, String description, T def) { + super(OptionType.Enumeration, name, description, def); + this.clazz = clazz; + } + + + public T[] values() { + return clazz.getEnumConstants(); + } + + + public Conversion convert(Object value) { + if (clazz.isInstance(value)) { + return valid(clazz.cast(value)); + } else if (value != null) { + + String str = value.toString().trim(); + Conversion conv; + try { + conv = valid(Enum.valueOf(clazz, str)); + } catch (IllegalArgumentException e) { + conv = invalid("Invalid value \"%s\" for %s", value, getName()); + } + + if (!conv.isOk()) { + // Try convert from an integer + try { + int x = Integer.parseInt(str); + T[] v = values(); + if (x > 0 && x < v.length) { + return valid(v[x]); + } + + } catch (NumberFormatException e) { + // Ignore .. we already have an error message from the string conversion + } + } + } + return invalid("%s is null", getName()); + } +} diff --git a/Annotation/src/ie/dcu/segment/options/IntegerOption.class b/Annotation/src/ie/dcu/segment/options/IntegerOption.class new file mode 100644 index 0000000..0f09407 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/IntegerOption.class differ diff --git a/Annotation/src/ie/dcu/segment/options/IntegerOption.java b/Annotation/src/ie/dcu/segment/options/IntegerOption.java new file mode 100644 index 0000000..c9f62b0 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/options/IntegerOption.java @@ -0,0 +1,79 @@ +package ie.dcu.segment.options; + +/** + * An integer segmentation algorithm parameter. + * + * @author Kevin McGuinness + */ +public class IntegerOption extends AbstractOption { + private final int min; + private final int max; + + + /** + * Create ain integer option with the given name, description, and default + * value. + * + * @param name + * The option name + * @param description + * A description of the option + * @param def + * The default value for the option + */ + public IntegerOption(String name, String description, int def) { + this(name, description, def, Integer.MIN_VALUE, Integer.MAX_VALUE); + } + + + /** + * Create an integer option with the given name, description, default + * value, minimum allowable value, and maximum allowable value. + * + * @param name + * The option name + * @param description + * A description of the option + * @param def + * The default value for the option + * @param min + * The minimum allowable value for the option + * @param max + * The maximum allowable value for the option + */ + public IntegerOption(String name, String description, int def, int min, int max) { + super(OptionType.Integer, name, description, def); + this.min = min; + this.max = max; + } + + + public Conversion convert(Object value) { + if (value instanceof Integer) { + return checkRange((Integer) value); + } else if (value != null) { + + try { + return checkRange(new Integer(value.toString().trim())); + } catch (NumberFormatException e) { + // Invalid + String mesg = e.getLocalizedMessage(); + return invalid("%s is not an integer: %s", getName(), mesg); + } + } + return invalid("%s is null", getName()); + } + + + private Conversion checkRange(int val) { + if (val >= min && val <= max) { + // OK + return valid(val); + + } + + // Out of range + String format = "%s must be in ther range (%d, %d), value is %d"; + return invalid(format, getName(), min, max, val); + } +} diff --git a/Annotation/src/ie/dcu/segment/options/Option.class b/Annotation/src/ie/dcu/segment/options/Option.class new file mode 100644 index 0000000..6850177 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/Option.class differ diff --git a/Annotation/src/ie/dcu/segment/options/Option.java b/Annotation/src/ie/dcu/segment/options/Option.java new file mode 100644 index 0000000..4778356 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/options/Option.java @@ -0,0 +1,57 @@ +package ie.dcu.segment.options; + +/** + * Interface for a segmentation algorithm parameter. + * + * @author Kevin McGuinness + */ +public interface Option { + + /** + * Return the option type + */ + public OptionType getType(); + + /** + * Try to convert a object to the required type for the option. + * + * @param value + * An object. + * @return A conversion object containing the result or an error message. + */ + public Conversion convert(Object value); + + /** + * Set the option to the given object value. + * + * @param value + * A value. + */ + public void setValue(Object value); + + /** + * Get the current value. + */ + public T getValue(); + + /** + * Get the default option value. + */ + public T getDefaultValue(); + + /** + * Returns all allowable values, or null. + */ + public T[] values(); + + /** + * Return the option name. + */ + public String getName(); + + /** + * Return a description of the option + */ + public String getDescription(); +} + diff --git a/Annotation/src/ie/dcu/segment/options/OptionEditor.class b/Annotation/src/ie/dcu/segment/options/OptionEditor.class new file mode 100644 index 0000000..8aa1462 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/OptionEditor.class differ diff --git a/Annotation/src/ie/dcu/segment/options/OptionType.class b/Annotation/src/ie/dcu/segment/options/OptionType.class new file mode 100644 index 0000000..c156f76 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/OptionType.class differ diff --git a/Annotation/src/ie/dcu/segment/options/OptionType.java b/Annotation/src/ie/dcu/segment/options/OptionType.java new file mode 100644 index 0000000..a05daef --- /dev/null +++ b/Annotation/src/ie/dcu/segment/options/OptionType.java @@ -0,0 +1,44 @@ +package ie.dcu.segment.options; + +/** + * Enumeration of segmentation algorithm parameter types. + * + * @author Kevin McGuinness + */ +public enum OptionType { + + /** + * A textual (string) option. + * + * @see TextOption + */ + Text, + + /** + * An integer option + * + * @see IntegerOption + */ + Integer, + + /** + * A decimal option + * + * @see DecimalOption + */ + Decimal, + + /** + * A toggle option + * + * @see ToggleOption + */ + Toggle, + + /** + * An enumerative option + * + * @see EnumOption + */ + Enumeration; +} diff --git a/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog$1.class b/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog$1.class new file mode 100644 index 0000000..f64a4c3 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog$1.class differ diff --git a/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog$StatusListener.class b/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog$StatusListener.class new file mode 100644 index 0000000..3300b95 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog$StatusListener.class differ diff --git a/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog.class b/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog.class new file mode 100644 index 0000000..2fe0abd Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog.class differ diff --git a/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog.java b/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog.java new file mode 100644 index 0000000..92a65e4 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/options/SegmenterOptionDialog.java @@ -0,0 +1,383 @@ +package ie.dcu.segment.options; + +import ie.dcu.segment.Segmenter; + +import java.util.*; +import java.util.List; + +import org.eclipse.jface.dialogs.*; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +/** + * Dynamically builds a dialog box for the segmentation algorithms options. + * + * @author Kevin McGuinness + */ +public class SegmenterOptionDialog extends TitleAreaDialog { + private final List editors; + private final Segmenter segmenter; + + + public SegmenterOptionDialog(Shell parent, Segmenter segmenter) { + super(parent); + + // Setup final fields + this.editors = new LinkedList(); + this.segmenter = segmenter; + + // Make it resizable + setShellStyle(getShellStyle() | SWT.RESIZE); + } + + + @Override + protected void okPressed() { + // Apply changes + for (OptionEditor editor : editors) { + editor.apply(); + } + + // Close + super.okPressed(); + } + + + @Override + protected Control createContents(Composite parent) { + Control contents = super.createContents(parent); + + // Set dialog title + getShell().setText("Segmenter Options"); + + // Set title area title + setTitle("Configure Segmenter Options"); + + // Set message + setMessage(String.format("Configure parameters for %s", + segmenter.getName())); + + // Done + return contents; + } + + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + + // Create scrolled area + ScrolledComposite scroller = new ScrolledComposite(composite, + SWT.H_SCROLL | SWT.V_SCROLL); + + // Configure scrolled area + scroller.setLayoutData(new GridData(GridData.FILL_BOTH)); + scroller.setExpandHorizontal(true); + scroller.setExpandVertical(true); + scroller.setAlwaysShowScrollBars(false); + + // Create content + Composite content = new Composite(scroller, SWT.NONE); + + // Create content layout + GridLayout layout = new GridLayout(); + layout.marginTop = layout.marginBottom = 10; + layout.marginLeft = layout.marginRight = 5; + layout.numColumns = 2; + content.setLayout(layout); + + // Create listener + StatusListener listener = new StatusListener(); + + // Add options + for (Option opt : segmenter.getOptions()) { + + // Create option label + Label label = new Label(content, SWT.NONE); + label.setText(opt.getName()); + label.setToolTipText(opt.getDescription()); + + // Create editor layout + GridData data = new GridData(); + data.horizontalIndent = 25; + data.grabExcessHorizontalSpace = true; + data.horizontalAlignment = SWT.FILL; + + // Create editor + OptionEditor editor = createEditor(content, opt); + editor.getControl().setLayoutData(data); + editor.addConversionListener(listener); + } + + // Set scroll area content + scroller.setContent(content); + + // Compute scroll area min size + scroller.setMinSize(content.computeSize( + SWT.DEFAULT, SWT.DEFAULT) + ); + + // Done + return composite; + } + + + @Override + protected Point getInitialSize() { + return new Point(450,350); + } + + + public OptionEditor createEditor(Composite parent, Option option) { + OptionEditor editor; + + // Use an combo editor for enums, otherwise use a text editor + switch (option.getType()) { + case Enumeration: + editor = new ComboEditor(parent, option); + break; + case Toggle: + editor = new ToggleEditor(parent, option); + break; + default: + editor = new TextEditor(parent, option); + } + + editors.add(editor); + return editor; + } + + + /** + * Updates error message and OK button status when a conversion occurs. + * + * @param conversion + * The conversion. + */ + private void handleConversion(Conversion conversion) { + boolean ok = false; + + if (conversion.isOk()) { + // Check all others + Conversion conv = null; + for (OptionEditor editor : editors) { + Conversion current = editor.convert(); + if (!current.isOk()) { + conv = current; + break; + } + } + if (conv == null) { + setErrorMessage(null); + ok = true; + } else { + setErrorMessage(conv.getMessage()); + } + } else { + + setErrorMessage(conversion.getMessage()); + } + + getButton(IDialogConstants.OK_ID).setEnabled(ok); + } + + + /** + * Updates error message when edits and focus changes occur. + */ + private final class StatusListener implements ConversionListener { + public void conversionPerformed(Conversion conversion) { + handleConversion(conversion); + } + } +} + + + + +interface ConversionListener { + public void conversionPerformed(Conversion conversion); +} + + +interface OptionEditor { + public Control getControl(); + public void addConversionListener(ConversionListener listener); + public void removeConversionListener(ConversionListener listener); + public void apply(); + public Conversion convert(); +} + + +abstract class AbstractEditor implements OptionEditor { + private final List listeners; + protected final Option option; + protected final Control control; + + public AbstractEditor(Composite parent, Option option) { + this.listeners = new ArrayList(1); + this.option = option; + this.control = createControl(parent, option); + } + + + public Control getControl() { + return control; + } + + + public void addConversionListener(ConversionListener listener) { + listeners.add(listener); + } + + + public void removeConversionListener(ConversionListener listener) { + listeners.remove(listener); + } + + + protected void fireConversionPerformed(Conversion conversion) { + for (ConversionListener listener : listeners) { + listener.conversionPerformed(conversion); + } + } + + + protected abstract Control createControl( + Composite parent, Option option + ); +} + + +class TextEditor extends AbstractEditor { + private Text text; + + + public TextEditor(Composite parent, Option option) { + super(parent, option); + } + + + @Override + protected Control createControl(Composite parent, Option opt) { + text = new Text(parent, SWT.BORDER); + text.setToolTipText(opt.getDescription()); + text.setText(opt.getValue().toString()); + + Verifier verifier = new Verifier(); + text.addModifyListener(verifier); + text.addFocusListener(verifier); + + return text; + } + + + public void apply() { + option.setValue(text.getText()); + } + + + public Conversion convert() { + return option.convert(text.getText()); + } + + + private final class Verifier extends FocusAdapter implements ModifyListener { + public void focusLost(FocusEvent e) { + fireConversionPerformed(convert()); + } + + + public void modifyText(ModifyEvent e) { + fireConversionPerformed(convert()); + } + } +} + + +class ComboEditor extends AbstractEditor { + private Combo combo; + private Object[] values; + + + public ComboEditor(Composite parent, Option option) { + super(parent, option); + } + + + @Override + protected Control createControl(Composite parent, Option opt) { + values = opt.values(); + + combo = new Combo(parent, SWT.READ_ONLY); + combo.setToolTipText(opt.getDescription()); + + for (Object v : values) { + combo.add(v.toString()); + } + + combo.setText(opt.getValue().toString()); + return combo; + } + + + public void apply() { + int idx = combo.getSelectionIndex(); + option.setValue(values[idx]); + } + + + public Conversion convert() { + int idx = combo.getSelectionIndex(); + return option.convert(values[idx]); + } +} + + +class ToggleEditor extends AbstractEditor { + private Button check; + + + public ToggleEditor(Composite parent, Option option) { + super(parent, option); + } + + + @Override + protected Control createControl(Composite parent, Option opt) { + check = new Button(parent, SWT.CHECK); + Boolean value = (Boolean) opt.getValue(); + check.setSelection(value); + check.addSelectionListener(new ToggleListener()); + updateText(); + return check; + } + + + private void updateText() { + boolean selection = check.getSelection(); + check.setText(selection ? "Yes" : "No"); + } + + + public void apply() { + option.setValue(check.getSelection()); + } + + + public Conversion convert() { + return option.convert(check.getSelection()); + } + + + private final class ToggleListener extends SelectionAdapter { + public void widgetSelected(SelectionEvent e) { + updateText(); + // No need to fire conversion event, will always be correct + } + } +} diff --git a/Annotation/src/ie/dcu/segment/options/TextEditor$1.class b/Annotation/src/ie/dcu/segment/options/TextEditor$1.class new file mode 100644 index 0000000..841695c Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/TextEditor$1.class differ diff --git a/Annotation/src/ie/dcu/segment/options/TextEditor$Verifier.class b/Annotation/src/ie/dcu/segment/options/TextEditor$Verifier.class new file mode 100644 index 0000000..525a7ce Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/TextEditor$Verifier.class differ diff --git a/Annotation/src/ie/dcu/segment/options/TextEditor.class b/Annotation/src/ie/dcu/segment/options/TextEditor.class new file mode 100644 index 0000000..85a4a7a Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/TextEditor.class differ diff --git a/Annotation/src/ie/dcu/segment/options/TextOption.class b/Annotation/src/ie/dcu/segment/options/TextOption.class new file mode 100644 index 0000000..f43cc3d Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/TextOption.class differ diff --git a/Annotation/src/ie/dcu/segment/options/TextOption.java b/Annotation/src/ie/dcu/segment/options/TextOption.java new file mode 100644 index 0000000..ff41daa --- /dev/null +++ b/Annotation/src/ie/dcu/segment/options/TextOption.java @@ -0,0 +1,29 @@ +package ie.dcu.segment.options; + +/** + * A textual (string) segmentation algorithm parameter. + * + * @author Kevin McGuinness + */ +public class TextOption extends AbstractOption { + + /** + * Create a text option with the given name, description, and default + * value. + * + * @param name + * The option name + * @param description + * A description of the option + * @param def + * The default value for the option + */ + public TextOption(String name, String description, String def) { + super(OptionType.Text, name, description, def); + } + + + public Conversion convert(Object value) { + return valid(value.toString()); + } +} diff --git a/Annotation/src/ie/dcu/segment/options/ToggleEditor$1.class b/Annotation/src/ie/dcu/segment/options/ToggleEditor$1.class new file mode 100644 index 0000000..84fa235 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/ToggleEditor$1.class differ diff --git a/Annotation/src/ie/dcu/segment/options/ToggleEditor$ToggleListener.class b/Annotation/src/ie/dcu/segment/options/ToggleEditor$ToggleListener.class new file mode 100644 index 0000000..fc0bb88 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/ToggleEditor$ToggleListener.class differ diff --git a/Annotation/src/ie/dcu/segment/options/ToggleEditor.class b/Annotation/src/ie/dcu/segment/options/ToggleEditor.class new file mode 100644 index 0000000..ff7efc6 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/ToggleEditor.class differ diff --git a/Annotation/src/ie/dcu/segment/options/ToggleOption.class b/Annotation/src/ie/dcu/segment/options/ToggleOption.class new file mode 100644 index 0000000..f94bcd6 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/options/ToggleOption.class differ diff --git a/Annotation/src/ie/dcu/segment/options/ToggleOption.java b/Annotation/src/ie/dcu/segment/options/ToggleOption.java new file mode 100644 index 0000000..c459fa1 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/options/ToggleOption.java @@ -0,0 +1,69 @@ +package ie.dcu.segment.options; + +/** + * A boolean segmentation algorithm parameter. + * + * @author Kevin McGuinness + */ +public class ToggleOption extends AbstractOption { + + /** + * Create a toggle option with the given name, description, and default + * value. + * + * @param name + * The option name + * @param description + * A description of the option + * @param def + * The default value for the option + */ + public ToggleOption(String name, String description, boolean def) { + super(OptionType.Toggle, name, description, def); + } + + + public Conversion convert(Object value) { + if (value instanceof Boolean) { + return valid((Boolean) value); + } else if (value != null) { + Boolean val = convert(value.toString()); + if (val != null) { + return valid(val); + } + return invalid("%s is not a valid boolean, value = %s", getName(), value); + } + return invalid("value is null"); + } + + + /** + * Performs a conversion from a string to a boolean. If the value is "yes", + * "true" or "1", then the result is true. Otherwise if the + * value is "no", "false" or "0" the result is false. Any + * other value produces null. The string is trimmed and case + * is ignored. + * + * @param str + * The string to convert. + * @return true, false or null. + */ + private Boolean convert(String str) { + String v = str.trim(); + + if (v.equalsIgnoreCase("true") || + v.equalsIgnoreCase("yes") || + v.equals("1")) + { + return true; + + } else if (v.equalsIgnoreCase("false") || + v.equalsIgnoreCase("no") || + v.equals("0")) + { + return false; + } + + return null; + } +} diff --git a/Annotation/src/ie/dcu/segment/painters/CombinedPainter.class b/Annotation/src/ie/dcu/segment/painters/CombinedPainter.class new file mode 100644 index 0000000..0b9388c Binary files /dev/null and b/Annotation/src/ie/dcu/segment/painters/CombinedPainter.class differ diff --git a/Annotation/src/ie/dcu/segment/painters/CombinedPainter.java b/Annotation/src/ie/dcu/segment/painters/CombinedPainter.java new file mode 100644 index 0000000..268a1dd --- /dev/null +++ b/Annotation/src/ie/dcu/segment/painters/CombinedPainter.java @@ -0,0 +1,136 @@ +package ie.dcu.segment.painters; + +import ie.dcu.segment.*; +import ie.dcu.swt.ObservableImage; + +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * An overlaid view of the image, segmentation mask, and markup. + * + * @author Kevin McGuinness + */ +public class CombinedPainter implements SegmentationPainter { + public static final String NAME = "Combined"; + + private ImageData maskData; + private Image maskImage; + + + public String getName() { + return NAME; + } + + + public String getDescription() { + return "An overlaid view of the image, segmentation mask, and markup"; + } + + + public void paint(SegmentationContext ctx, ObservableImage im) { + + GC gc = im.beginPaint(); + + // Paint image + gc.drawImage(ctx.getImage(), 0, 0); + + // Paint mask + createVisibleMask(ctx.getMask()); + gc.drawImage(maskImage, 0, 0); + + // Paint all annotations + ctx.getAnnotations().paint(im); + + // Commit changes + im.endPaint(); + } + + + private void createVisibleMask(SegmentationMask mask) { + dispose(); + + if (isNewMaskDataRequired(mask.getBounds())) { + maskData = createMaskData(mask.getBounds()); + } + + // Blit in pixels + for (int y = 0, i = 0; y < mask.height; y++) { + int rowOffset = y * maskData.bytesPerLine; + for (int x = 0; x < mask.width; x++) { + byte alpha, index; + + switch (mask.values[i]) { + case SegmentationMask.BACKGROUND: + alpha = (byte) 128; + index = 2; + break; + case SegmentationMask.FOREGROUND: + alpha = (byte) 128; + index = 1; + break; + default: + alpha = 0; + index = 0; + break; + } + + // The SWT ImageData buffer doesn't usually have it's rows aligned + // contiguously in memory (i.e. there are > width bytes per scan-line in + // the buffer), so we can't directly copy in at the same index as the + // mask. + maskData.data[x + rowOffset] = index; + + // However, the alpha data is always aligned correctly + maskData.alphaData[i] = alpha; + + // Next location in the mask + i++; + } + } + + // Create new mask + maskImage = new Image(Display.getCurrent(), maskData); + } + + + private boolean isNewMaskDataRequired(Rectangle bounds) { + if (maskData == null) { + return true; + } else { + return maskData.width != bounds.width || maskData.height != bounds.height; + } + } + + + private static ImageData createMaskData(Rectangle bounds) { + RGB[] colors = new RGB[] { + new RGB(128,128,128), + new RGB(255,255,255), + new RGB(0, 0, 0) + }; + + // Create 3 color indexed palette + PaletteData palette = new PaletteData(colors); + + // Create 8 bit indexed image + ImageData data = new ImageData(bounds.width, bounds.height, 8, palette); + + // Create alpha mask + data.alphaData = new byte[bounds.width*bounds.height]; + + // Create and return the image + return data; + } + + + public void dispose() { + // Dispose mask + if (maskImage != null) { + if (!maskImage.isDisposed()) { + maskImage.dispose(); + } + maskImage = null; + } + } +} diff --git a/Annotation/src/ie/dcu/segment/painters/ForegroundOnlyPainter.class b/Annotation/src/ie/dcu/segment/painters/ForegroundOnlyPainter.class new file mode 100644 index 0000000..8b2c9bb Binary files /dev/null and b/Annotation/src/ie/dcu/segment/painters/ForegroundOnlyPainter.class differ diff --git a/Annotation/src/ie/dcu/segment/painters/ForegroundOnlyPainter.java b/Annotation/src/ie/dcu/segment/painters/ForegroundOnlyPainter.java new file mode 100644 index 0000000..ed8bc4e --- /dev/null +++ b/Annotation/src/ie/dcu/segment/painters/ForegroundOnlyPainter.java @@ -0,0 +1,114 @@ +package ie.dcu.segment.painters; + + +import ie.dcu.segment.*; +import ie.dcu.swt.ObservableImage; + +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * Shows the foreground region of the image. The background is greyed out. + * + * @author Kevin McGuinness + */ +public class ForegroundOnlyPainter implements SegmentationPainter { + + private ImageData maskData; + private Image maskImage; + + + public String getName() { + return "Foreground Only"; + } + + + public String getDescription() { + return "Shows the foreground region of the image."; + } + + + public void paint(SegmentationContext ctx, ObservableImage im) { + GC gc = im.beginPaint(); + + // Paint image + gc.drawImage(ctx.getImage(), 0, 0); + + // Paint mask + createVisibleMask(ctx.getMask()); + gc.drawImage(maskImage, 0, 0); + + // Commit changes + im.endPaint(); + } + + + private void createVisibleMask(SegmentationMask mask) { + dispose(); + + if (isNewMaskDataRequired(mask.getBounds())) { + maskData = createMaskData(mask.getBounds()); + } + + // Blit in pixels + byte[] buff = new byte[maskData.width]; + for (int y = 0, i = 0; y < mask.height; y++) { + for (int x = 0; x < mask.width; x++) { + switch (mask.values[i++]) { + case SegmentationMask.BACKGROUND: + // black + buff[x] = 1; + break; + default: + // transparent + buff[x] = 0; + } + } + maskData.setPixels(0, y, buff.length, buff, 0); + } + + // Create new mask + maskImage = new Image(Display.getCurrent(), maskData); + } + + + private boolean isNewMaskDataRequired(Rectangle bounds) { + if (maskData == null) { + return true; + } else { + return maskData.width != bounds.width || maskData.height != bounds.height; + } + } + + + private static ImageData createMaskData(Rectangle bounds) { + RGB[] colors = new RGB[] { + new RGB(255,255,255), + new RGB(128,128,128) + }; + + // Create binary indexed palette + PaletteData palette = new PaletteData(colors); + + // Create 1 bit indexed image + ImageData data = new ImageData( + bounds.width, bounds.height, 1, palette); + + // Set transparent pixel + data.transparentPixel = 0; + + // Create and return the image + return data; + } + + + public void dispose() { + // Dispose mask + if (maskImage != null) { + if (!maskImage.isDisposed()) { + maskImage.dispose(); + } + maskImage = null; + } + } +} diff --git a/Annotation/src/ie/dcu/segment/painters/LabelPainter.java b/Annotation/src/ie/dcu/segment/painters/LabelPainter.java new file mode 100644 index 0000000..1362931 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/painters/LabelPainter.java @@ -0,0 +1,114 @@ +package ie.dcu.segment.painters; + + +import ie.dcu.segment.*; +import ie.dcu.swt.ObservableImage; + +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * Shows the foreground region of the image. The background is greyed out. + * + * @author Kevin and Nikhil + */ +public class LabelPainter implements SegmentationPainter { + + private ImageData maskData; + private Image maskImage; + + + public String getName() { + return "Display Label"; + } + + + public String getDescription() { + return "Shows the segmented piece with label attached."; + } + + + public void paint(SegmentationContext ctx, ObservableImage im) { + GC gc = im.beginPaint(); + + // Paint image + gc.drawImage(ctx.getImage(), 0, 0); + + // Paint mask + createVisibleMask(ctx.getMask()); + gc.drawImage(maskImage, 0, 0); + + // Commit changes + im.endPaint(); + } + + + private void createVisibleMask(SegmentationMask mask) { + dispose(); + + if (isNewMaskDataRequired(mask.getBounds())) { + maskData = createMaskData(mask.getBounds()); + } + + // Blit in pixels + byte[] buff = new byte[maskData.width]; + for (int y = 0, i = 0; y < mask.height; y++) { + for (int x = 0; x < mask.width; x++) { + switch (mask.values[i++]) { + case SegmentationMask.BACKGROUND: + // black + buff[x] = 1; + break; + default: + // transparent + buff[x] = 0; + } + } + maskData.setPixels(0, y, buff.length, buff, 0); + } + + // Create new mask + maskImage = new Image(Display.getCurrent(), maskData); + } + + + private boolean isNewMaskDataRequired(Rectangle bounds) { + if (maskData == null) { + return true; + } else { + return maskData.width != bounds.width || maskData.height != bounds.height; + } + } + + + private static ImageData createMaskData(Rectangle bounds) { + RGB[] colors = new RGB[] { + new RGB(255,255,255), + new RGB(128,128,128) + }; + + // Create binary indexed palette + PaletteData palette = new PaletteData(colors); + + // Create 1 bit indexed image + ImageData data = new ImageData( + bounds.width, bounds.height, 1, palette); + + // Set transparent pixel + data.transparentPixel = 0; + + // Create and return the image + return data; + } + + + public void dispose() { + // Dispose mask + if (maskImage != null) { + if (!maskImage.isDisposed()) { + maskImage.dispose(); + } + maskImage = null; + } + } +} diff --git a/Annotation/src/ie/dcu/segment/painters/MarkupPainter.class b/Annotation/src/ie/dcu/segment/painters/MarkupPainter.class new file mode 100644 index 0000000..4dbb4e7 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/painters/MarkupPainter.class differ diff --git a/Annotation/src/ie/dcu/segment/painters/MarkupPainter.java b/Annotation/src/ie/dcu/segment/painters/MarkupPainter.java new file mode 100644 index 0000000..24b5fbf --- /dev/null +++ b/Annotation/src/ie/dcu/segment/painters/MarkupPainter.java @@ -0,0 +1,48 @@ +package ie.dcu.segment.painters; + + +import ie.dcu.segment.SegmentationContext; +import ie.dcu.swt.*; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.GC; + +/** + * Shows the current markup (annotations) only + * + * @author Kevin McGuinness + */ +public class MarkupPainter implements SegmentationPainter { + public static final String NAME = "Markup"; + + + public String getDescription() { + return "Shows the current markup (annotations) only"; + } + + + public String getName() { + return NAME; + } + + + public void paint(SegmentationContext ctx, ObservableImage im) { + + GC gc = im.beginPaint(); + + // Paint white backdrop + SwtUtils.setBackground(gc, SWT.COLOR_WHITE); + gc.fillRectangle(im.getBounds()); + + // Paint all annotations + ctx.getAnnotations().paint(im); + + // Commit changes + im.endPaint(); + } + + + public void dispose() { + // Nothing needs to be disposed + } +} diff --git a/Annotation/src/ie/dcu/segment/painters/MaskPainter.class b/Annotation/src/ie/dcu/segment/painters/MaskPainter.class new file mode 100644 index 0000000..8a236f0 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/painters/MaskPainter.class differ diff --git a/Annotation/src/ie/dcu/segment/painters/MaskPainter.java b/Annotation/src/ie/dcu/segment/painters/MaskPainter.java new file mode 100644 index 0000000..192f368 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/painters/MaskPainter.java @@ -0,0 +1,98 @@ +package ie.dcu.segment.painters; + +import ie.dcu.segment.*; +import ie.dcu.swt.ObservableImage; + +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * Shows the current segmentation mask + * + * @author Kevin McGuinness + */ +public class MaskPainter implements SegmentationPainter { + public static final String NAME = "Mask"; + + private ImageData maskData; + private Image maskImage; + + public String getDescription() { + return "Shows the current segmentation mask"; + } + + + public String getName() { + return NAME; + } + + + public void paint(SegmentationContext ctx, ObservableImage im) { + + GC gc = im.beginPaint(); + + // Paint mask + createVisibleMask(ctx.getMask()); + gc.drawImage(maskImage, 0, 0); + + // Commit changes + im.endPaint(); + } + + + private void createVisibleMask(SegmentationMask mask) { + dispose(); + + // Check if we have a compatible buffer + if (isNewMaskDataRequired(mask.getBounds())) { + maskData = createMaskData(mask.getBounds()); + } + + // Blit in pixels + for (int y = 0; y < mask.height; y++) { + int maskOffset = y * mask.width; + int dataOffset = y * maskData.bytesPerLine; + System.arraycopy(mask.values, maskOffset, maskData.data, dataOffset, mask.width); + } + + // Create new mask + maskImage = new Image(Display.getCurrent(), maskData); + } + + private boolean isNewMaskDataRequired(Rectangle bounds) { + if (maskData == null) { + return true; + } else { + return maskData.width != bounds.width || maskData.height != bounds.height; + } + } + + + private static ImageData createMaskData(Rectangle bounds) { + RGB[] colors = new RGB[] { + new RGB(128,128,128), + new RGB(255,255,255), + new RGB(0, 0, 0) + }; + + // Create 3 color indexed palette + PaletteData palette = new PaletteData(colors); + + // Create 8 bit indexed image + ImageData data = new ImageData(bounds.width, bounds.height, 8, palette); + + // Create and return the image + return data; + } + + + public void dispose() { + /// Dispose mask + if (maskImage != null) { + if (!maskImage.isDisposed()) { + maskImage.dispose(); + } + maskImage = null; + } + } +} diff --git a/Annotation/src/ie/dcu/segment/painters/OriginalPainter.class b/Annotation/src/ie/dcu/segment/painters/OriginalPainter.class new file mode 100644 index 0000000..70bbe58 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/painters/OriginalPainter.class differ diff --git a/Annotation/src/ie/dcu/segment/painters/OriginalPainter.java b/Annotation/src/ie/dcu/segment/painters/OriginalPainter.java new file mode 100644 index 0000000..97bdfca --- /dev/null +++ b/Annotation/src/ie/dcu/segment/painters/OriginalPainter.java @@ -0,0 +1,42 @@ +package ie.dcu.segment.painters; + +import ie.dcu.segment.SegmentationContext; +import ie.dcu.swt.ObservableImage; + +import org.eclipse.swt.graphics.*; + +/** + * Shows the original image + * + * @author Kevin McGuinness + */ +public class OriginalPainter implements SegmentationPainter { + public static final String NAME = "Original"; + + + public String getDescription() { + return "Shows the original image"; + } + + + public String getName() { + return NAME; + } + + + public void paint(SegmentationContext ctx, ObservableImage im) { + GC gc = im.beginPaint(); + + // Paint image + gc.drawImage(ctx.getImage(), 0, 0); + + // Commit changes + im.endPaint(); + } + + + public void dispose() { + // Nothing needs to be disposed + } + +} diff --git a/Annotation/src/ie/dcu/segment/painters/OutlineOverlayPainter.class b/Annotation/src/ie/dcu/segment/painters/OutlineOverlayPainter.class new file mode 100644 index 0000000..fe61d10 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/painters/OutlineOverlayPainter.class differ diff --git a/Annotation/src/ie/dcu/segment/painters/OutlineOverlayPainter.java b/Annotation/src/ie/dcu/segment/painters/OutlineOverlayPainter.java new file mode 100644 index 0000000..41cc8d6 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/painters/OutlineOverlayPainter.java @@ -0,0 +1,145 @@ +package ie.dcu.segment.painters; + +import ie.dcu.segment.*; +import ie.dcu.swt.ObservableImage; + +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * Shows an an overlay of foreground border on the image + * + * @author Kevin McGuinness + */ +public class OutlineOverlayPainter implements SegmentationPainter { + + private ImageData maskData; + private Image maskImage; + + public String getName() { + return "Outline Overlaid"; + } + + + public String getDescription() { + return "Shows an an overlay of foreground border on the image"; + } + + + public void paint(SegmentationContext ctx, ObservableImage im) { + GC gc = im.beginPaint(); + + // Paint image + gc.drawImage(ctx.getImage(), 0, 0); + + // Paint mask + createVisibleMask(ctx.getMask()); + gc.drawImage(maskImage, 0, 0); + + // Commit changes + im.endPaint(); + } + + + private void createVisibleMask(SegmentationMask mask) { + dispose(); + + if (isNewMaskDataRequired(mask.getBounds())) { + maskData = createMaskData(mask.getBounds()); + } + + // Set pixels + byte[] buff = new byte[maskData.width]; + for (int y = 0, i = 0; y < mask.height-1; y++) { + for (int x = 0; x < mask.width-1; x++) { + // Make transparent + buff[x] = 0; + + // Current pixel + byte pix1 = mask.values[i]; + + // Neighbor to right & neighbor below + byte pix2 = mask.values[i+1]; + byte pix3 = mask.values[i+mask.width]; + + // Set pixel if either neighbor is different + if (pix1 != pix2 || pix1 != pix3) { + buff[x] = 1; + } + + // Next pixel + i++; + } + + if (mask.width != 0) { + // Last pixel in row + byte pix1 = mask.values[i]; + byte pix2 = mask.values[i+mask.width]; + buff[mask.width-1] = (pix1 != pix2) ? (byte) 1 : 0; + + // Next row + i++; + } + + // Blit pixels + maskData.setPixels(0, y, buff.length, buff, 0); + } + + // Last row + if (mask.height != 0) { + int yoff = (mask.height - 1) * mask.width; + for (int x = 0; x < mask.width-1; x++) { + byte pix1 = mask.values[x+yoff]; + byte pix2 = mask.values[x+yoff+1]; + buff[x] = (pix1 != pix2) ? (byte) 1 : 0; + } + + // Blit + maskData.setPixels(0, mask.height-1, buff.length, buff, 0); + } + + // Create new mask + maskImage = new Image(Display.getCurrent(), maskData); + } + + + private boolean isNewMaskDataRequired(Rectangle bounds) { + if (maskData == null) { + return true; + } else { + return maskData.width != bounds.width || maskData.height != bounds.height; + } + } + + + private static ImageData createMaskData(Rectangle bounds) { + RGB[] colors = new RGB[] { + new RGB(255,255,255), + new RGB(255,0,0) + }; + + // Create binary indexed palette + PaletteData palette = new PaletteData(colors); + + // Create 1 bit indexed image + ImageData data = new ImageData( + bounds.width, bounds.height, 1, palette); + + // Set transparent pixel + data.transparentPixel = 0; + + // Create and return the image + return data; + } + + + public void dispose() { + // Dispose mask + if (maskImage != null) { + if (!maskImage.isDisposed()) { + maskImage.dispose(); + } + maskImage = null; + } + } +} diff --git a/Annotation/src/ie/dcu/segment/painters/SegmentationPainter.class b/Annotation/src/ie/dcu/segment/painters/SegmentationPainter.class new file mode 100644 index 0000000..eadcd40 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/painters/SegmentationPainter.class differ diff --git a/Annotation/src/ie/dcu/segment/painters/SegmentationPainter.java b/Annotation/src/ie/dcu/segment/painters/SegmentationPainter.java new file mode 100644 index 0000000..4989f60 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/painters/SegmentationPainter.java @@ -0,0 +1,39 @@ +package ie.dcu.segment.painters; + +import ie.dcu.segment.SegmentationContext; +import ie.dcu.swt.ObservableImage; + +/** + * Interface for classes that can be used to visualize an image and it's + * segmentation mask. + * + * + * @author Kevin McGuinness + */ +public interface SegmentationPainter { + + /** + * Returns the painter name (Shown in the UI) + */ + public String getName(); + + /** + * Returns a description of the painter. + */ + public String getDescription(); + + /** + * Paint the segmentation context onto the observable image + * + * @param ctx + * The current segmentation context. + * @param im + * An observable image instance. + */ + public void paint(SegmentationContext ctx, ObservableImage im); + + /** + * Dispose of any resources (SWT image objects, colors, etc.) + */ + public void dispose(); +} diff --git a/Annotation/src/ie/dcu/segment/util/AbstractSegmenter.class b/Annotation/src/ie/dcu/segment/util/AbstractSegmenter.class new file mode 100644 index 0000000..38a83d6 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/util/AbstractSegmenter.class differ diff --git a/Annotation/src/ie/dcu/segment/util/AbstractSegmenter.java b/Annotation/src/ie/dcu/segment/util/AbstractSegmenter.java new file mode 100644 index 0000000..c8e8928 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/util/AbstractSegmenter.java @@ -0,0 +1,226 @@ +package ie.dcu.segment.util; + + + +import ie.dcu.array.Arrays; +import ie.dcu.image.binary.MorphOp; +import ie.dcu.matrix.*; +import ie.dcu.segment.*; +import ie.dcu.segment.annotate.Annotation; +import ie.dcu.segment.options.Option; + +import java.util.*; +import java.util.logging.*; + +/** + * Abstract implementation of a {@link Segmenter} object. + * + * @author Kevin McGuinness + */ +public abstract class AbstractSegmenter implements Segmenter { + + /** + * Segmenter options map. + */ + private final Map> options; + + + /** + * Logger for subclass messages. + */ + protected final Logger log; + + + /** + * Name of the segmentation algorithm. Should be set by subclass during + * construction. + */ + protected String name; + + + /** + * Description of the segmentation algorithm. Should be set by subclass + * during construction. + */ + protected String description; + + + /** + * Vendor of the segmentation algorithm. Should be set by subclass + * during construction. This should be either the author of the + * segmentation algorithm, or a company or institution name. + */ + protected String vendor; + + + /** + * Default return value for the {@link #isFast()} method, + * false by default. + */ + protected boolean fast; + + + /** + * Flag that indicates if the segmentation algorithm is available on the + * current platform. Defaults to true. + */ + protected boolean available; + + + /** + * Constructor. + */ + public AbstractSegmenter() { + options = new LinkedHashMap>(); + log = Logger.getLogger(getClass().getSimpleName()); + name = ""; + description = ""; + vendor = ""; + available = true; + } + + + /** + * Default implementation returns the {@link #available} field. + */ + public boolean isAvailable() { + return available; + } + + + /** + * Default implementation returns the {@link #name} field. + */ + public String getName() { + return name; + } + + + /** + * Default implementation returns the {@link #description} field. + */ + public String getDescription() { + return description; + } + + + /** + * Default implementation returns the {@link #vendor} field. + */ + public String getVendor() { + return vendor; + } + + + /** + * Default implementation returns the {@link #options} map. + */ + public Collection> getOptions() { + return Collections.unmodifiableCollection(options.values()); + } + + + /** + * Default implementation returns the {@link #fast} field. + */ + public boolean isFast() { + return fast; + } + + + /** + * Default implementation calls {@link #segment(SegmentationContext)}. + */ + public void added(SegmentationContext ctx, Annotation a) { + segment(ctx); + } + + + /** + * Default implementation calls {@link #segment(SegmentationContext)}. + */ + public void removed(SegmentationContext ctx, Annotation a) { + segment(ctx); + } + + + /** + * Default implementation calls {@link #segment(SegmentationContext)}. + */ + public void update(SegmentationContext ctx) { + segment(ctx); + } + + + + /** + * Perform a full update of the segmentation. + * + * @param ctx + * The segmentation context. + */ + protected abstract void segment(SegmentationContext ctx); + + + + /** + * Add an option (parameter) to the {@link #options} map. + * + * @param option + * The option + */ + protected void add(Option option) { + options.put(option.getName(), option); + } + + + /** + * Get an option (parameter) from the {@link #options} map. + * + * @param + * The option type. + * @param clazz + * The option class. + * @param option + * The option name. + * @return The option. + */ + protected T get(Class clazz, String option) { + Option opt = options.get(option); + return clazz.cast(opt.getValue()); + } + + /** + * Perform a morphological smooth on the contour of the given segmentation + * mask. + * + * @param mask + * A segmentation mask. + */ + protected void smoothContour(SegmentationMask mask) { + // TODO: Maybe optimize this? The old MorphOps.smooth might be faster + MorphOp op = new MorphOp.Smooth(); + op.setForegroundValue(SegmentationMask.FOREGROUND); + op.setBackgroundValue(SegmentationMask.BACKGROUND); + op.setInputProvider(mask); + ByteMatrix matrix = (ByteMatrix) + op.getMatrix(Matrix.Type.Byte, false); + Arrays.copy(matrix.values, mask.values); + } + + /** + * Copy the non-zero markup pixels to the segmentation mask. + * + * @param mask + * The segmentation mask. + * @param markup + * The rasterized markup pixels. + */ + protected void retainMarkup(SegmentationMask mask, byte[] markup) { + for (int i = 0; i < markup.length; i++) { + if (markup[i] != 0) { + mask.values[i] = markup[i]; + } + } + } +} diff --git a/Annotation/src/ie/dcu/segment/util/AnnotationRasterizer$1.class b/Annotation/src/ie/dcu/segment/util/AnnotationRasterizer$1.class new file mode 100644 index 0000000..d6f5b16 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/util/AnnotationRasterizer$1.class differ diff --git a/Annotation/src/ie/dcu/segment/util/AnnotationRasterizer.class b/Annotation/src/ie/dcu/segment/util/AnnotationRasterizer.class new file mode 100644 index 0000000..2ef4569 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/util/AnnotationRasterizer.class differ diff --git a/Annotation/src/ie/dcu/segment/util/AnnotationRasterizer.java b/Annotation/src/ie/dcu/segment/util/AnnotationRasterizer.java new file mode 100644 index 0000000..144d40c --- /dev/null +++ b/Annotation/src/ie/dcu/segment/util/AnnotationRasterizer.java @@ -0,0 +1,145 @@ +package ie.dcu.segment.util; + +import ie.dcu.segment.annotate.*; + +import java.awt.*; +import java.awt.image.*; +import java.util.List; + +import org.eclipse.swt.graphics.Point; + +/** + * Rasterize the annotations using the Graphics2D API. The annotations are drawn + * onto a byte buffer, with one byte per pixel. + * + * @author Kevin McGuinness + */ +public class AnnotationRasterizer { + private static final byte[] R = { (byte) 128, (byte) 255, (byte) 0 }; + private static final byte[] G = { (byte) 128, (byte) 0, (byte) 0 }; + private static final byte[] B = { (byte) 128, (byte) 0, (byte) 255 }; + + private static final Color[] COLORS = { + new Color(128, 128, 128), + new Color(255, 0, 0), + new Color( 0, 0, 255) + }; + + private static final ColorModel cm = new IndexColorModel(8,3,R,G,B); + + private final int width; + private final int height; + private final int npixels; + private final WritableRaster wr; + private final BufferedImage im; + private transient byte[] buff; + + public AnnotationRasterizer(int width, int height) { + this.width = width; + this.height = height; + this.npixels = width * height; + this.wr = cm.createCompatibleWritableRaster(width, height); + this.im = new BufferedImage(cm, wr, false, null); + } + + + public byte[] rasterize(AnnotationManager am) { + paint(am); + return getDataBuffer(); + } + + + private void paint(AnnotationManager am) { + + Graphics2D g = im.createGraphics(); + + // Clear background + g.setColor(COLORS[0]); + g.fillRect(0, 0, width, height); + + // For each annotation + int lastWidth = -1; + for (Annotation a : am.annotations()) { + + List pts = a.points(); + + // Skip empty + if (pts.size() == 0) { + continue; + } + + // Check if we need to change the stroke + int width = a.getLineWidth(); + if (width != lastWidth) { + g.setStroke(createStroke(width)); + lastWidth = width; + } + + // Set the color + switch (a.getType()) { + case Foreground: + g.setColor(COLORS[1]); + break; + case Background: + g.setColor(COLORS[2]); + break; + } + + // Paint the points + if (pts.size() > 1) { + Point last = null; + for (Point p : pts) { + if (last != null) { + g.drawLine(last.x, last.y, p.x, p.y); + } + + last = p; + } + } else { + // If only one point + Point p = pts.get(0); + g.drawLine(p.x, p.y, p.x, p.y); + } + } + + // Commit changes + g.dispose(); + } + + + private byte[] getDataBuffer() { + + // Optimize the typical case by avoiding a copy if unnecessary. + DataBuffer buffer = wr.getDataBuffer(); + if (buffer instanceof DataBufferByte) { + + // Good, we have a compatible data buffer + DataBufferByte bytebuf = (DataBufferByte) buffer; + int banks = bytebuf.getNumBanks(); + if (banks == 1) { + + // Smashin, only one data bank is in use + byte[] buff = bytebuf.getData(); + + // Sanity check + if (buff.length == npixels) { + return buff; + } + } + } + + // Handle some unexpected data buffer by copying pixels + if (buff == null) { + buff = new byte[npixels]; + } + + return (byte[]) wr.getDataElements(0, 0, width, height, buff); + } + + + + private static final Stroke createStroke(int width) { + return new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + } + +} diff --git a/Annotation/src/ie/dcu/segment/util/ImageArgbConverter.class b/Annotation/src/ie/dcu/segment/util/ImageArgbConverter.class new file mode 100644 index 0000000..27b92b2 Binary files /dev/null and b/Annotation/src/ie/dcu/segment/util/ImageArgbConverter.class differ diff --git a/Annotation/src/ie/dcu/segment/util/ImageArgbConverter.java b/Annotation/src/ie/dcu/segment/util/ImageArgbConverter.java new file mode 100644 index 0000000..ab314ed --- /dev/null +++ b/Annotation/src/ie/dcu/segment/util/ImageArgbConverter.java @@ -0,0 +1,99 @@ +package ie.dcu.segment.util; + +import org.eclipse.swt.graphics.*; + +/** + * Convert a SWT ImageData object to a linear array of ARGB integers (alpha + * channel is ignored). + * + * @author Kevin McGuinness + */ +public class ImageArgbConverter { + private final int npixels; + private final int[] pixels; + + /** + * Create an converter object for images of the given size. + * + * @param width + * The image width. + * @param height + * The image height. + */ + public ImageArgbConverter(int width, int height) { + npixels = width*height; + pixels = new int[npixels]; + } + + + /** + * Convert an SWT ImageData object to a linear array of integers. Each + * integer is a contains the red, green, and blue channels, ordered as + * 0x00RRGGBB. The alpha channel is ignored. + * + * @param data + * An image data object. + * @param clone + * If false returns a shared array, otherwise returns a + * new array. + * @return A int array of ARGB values in row-major order. + */ + public int[] convert(ImageData data, boolean clone) { + PaletteData p = data.palette; + + data.getPixels(0, 0, npixels, pixels, 0); + if (p.isDirect) { + for (int i = 0; i < npixels; i++) { + // Unpack + int r, g, b, pel = pixels[i]; + + // red + r = pel & p.redMask; + r = (p.redShift < 0) ? + r >>> -p.redShift : r << p.redShift; + + // green + g = pel & p.greenMask; + g = (p.greenShift < 0) ? + g >>> -p.greenShift : g << p.greenShift; + + // blue + b = pel & p.blueMask; + b = (p.blueShift < 0) ? + b >>> -p.blueShift : b << p.blueShift; + + // re-pack + pixels[i] = pack(r, g, b); + } + } else { + // Indirect palette + for (int i = 0; i < npixels; i++) { + RGB color = p.colors[pixels[i]]; + pixels[i] = pack(color.red, color.green, color.blue); + } + } + + if (clone) { + return pixels.clone(); + } + + return pixels; + } + + /** + * Convert an SWT ImageData object to a linear array of integers. Each + * integer is a contains the red, green, and blue channels, ordered as + * 0x00RRGGBB. The alpha channel is ignored. + * + * @param data + * An image data object. + * @return A int array of ARGB values in row-major order. + */ + public static int[] convert(ImageData data) { + return new ImageArgbConverter(data.width, data.height).convert(data, false); + } + + private static final int pack(int r, int g, int b) { + return 0x00ffffff & ((r << 16) | (g << 8) | b); + } +} diff --git a/Annotation/src/ie/dcu/segment/util/ImageByteConverter.class b/Annotation/src/ie/dcu/segment/util/ImageByteConverter.class new file mode 100644 index 0000000..460930d Binary files /dev/null and b/Annotation/src/ie/dcu/segment/util/ImageByteConverter.class differ diff --git a/Annotation/src/ie/dcu/segment/util/ImageByteConverter.java b/Annotation/src/ie/dcu/segment/util/ImageByteConverter.java new file mode 100644 index 0000000..df33c66 --- /dev/null +++ b/Annotation/src/ie/dcu/segment/util/ImageByteConverter.java @@ -0,0 +1,101 @@ +package ie.dcu.segment.util; + +import org.eclipse.swt.graphics.*; + +/** + * Converts an SWT ImageData object to a linear array of bytes. + * + * @author Kevin McGuinness + */ +public class ImageByteConverter { + private final int npixels; + private final int nsamples; + private final int[] pixels; + private final byte[] samples; + + /** + * Create an converter object for images of the given size. + * + * @param width + * The image width. + * @param height + * The image height. + */ + public ImageByteConverter(int width, int height) { + this.npixels = width*height; + this.nsamples = npixels*3; + this.pixels = new int[npixels]; + this.samples = new byte[nsamples]; + } + + /** + * Convert an SWT ImageData object to a linear array of bytes. The returned + * array contains three bytes per pixel, and is in row-major order. The + * bytes are ordered RGB. + * + * @param data + * An image data object. + * @param clone + * If false returns a shared array, otherwise returns a + * new array. + * @return A byte array of RGB values in row-major order. + */ + public byte[] convert(ImageData data, boolean clone) { + PaletteData p = data.palette; + + data.getPixels(0, 0, npixels, pixels, 0); + if (p.isDirect) { + for (int i = 0, j = 0; i < npixels; i++) { + // Unpack + int r, g, b, pel = pixels[i]; + + // red + r = pel & p.redMask; + r = (p.redShift < 0) ? + r >>> -p.redShift : r << p.redShift; + + // green + g = pel & p.greenMask; + g = (p.greenShift < 0) ? + g >>> -p.greenShift : g << p.greenShift; + + // blue + b = pel & p.blueMask; + b = (p.blueShift < 0) ? + b >>> -p.blueShift : b << p.blueShift; + + // assign + samples[j++] = (byte) r; + samples[j++] = (byte) g; + samples[j++] = (byte) b; + } + } else { + // Indirect palette + for (int i = 0, j = 0; i < npixels; i++) { + RGB color = p.colors[pixels[i]]; + samples[j++] = (byte) color.red; + samples[j++] = (byte) color.green; + samples[j++] = (byte) color.blue; + } + } + + if (clone) { + return samples.clone(); + } + + return samples; + } + + /** + * Convert an SWT image data object to a linear array of bytes. The returned + * array contains three bytes per pixel, and is in row-major order. The + * bytes are ordered RGB. + * + * @param data + * An image data object. + * @return A byte array of RGB values in row-major order. + */ + public static byte[] convert(ImageData data) { + return new ImageByteConverter(data.width, data.height).convert(data, false); + } +} diff --git a/Annotation/src/ie/dcu/stats/InversionMethod$1.class b/Annotation/src/ie/dcu/stats/InversionMethod$1.class new file mode 100644 index 0000000..8f7acd5 Binary files /dev/null and b/Annotation/src/ie/dcu/stats/InversionMethod$1.class differ diff --git a/Annotation/src/ie/dcu/stats/InversionMethod.class b/Annotation/src/ie/dcu/stats/InversionMethod.class new file mode 100644 index 0000000..e68f5be Binary files /dev/null and b/Annotation/src/ie/dcu/stats/InversionMethod.class differ diff --git a/Annotation/src/ie/dcu/stats/InversionMethod.java b/Annotation/src/ie/dcu/stats/InversionMethod.java new file mode 100644 index 0000000..24cb901 --- /dev/null +++ b/Annotation/src/ie/dcu/stats/InversionMethod.java @@ -0,0 +1,254 @@ +package ie.dcu.stats; + +import java.awt.*; +import java.awt.geom.*; + +import javax.swing.*; + +import ie.dcu.array.Arrays; +import static java.awt.RenderingHints.*; + +/** + * Implementation of the inversion method for simulating random variables. + * + * @author Kevin McGuinness + */ +public final class InversionMethod { + + /** + * The probability distribution function + */ + private final double[] pdf; + + /** + * The cumulative distribution function + */ + private final double[] cdf; + + + /** + * Initialize the inversion method with the given discrete probability + * distribution function. The distribution function will be normalized the + * sum of all it's elements is one. + * + * The values of the pdf function must be all greater than 0 and contain at + * least one positive value. + * + * @param pdf + * A probability distribution function. + */ + public InversionMethod(double[] pdf) { + this.pdf = normalize(check(pdf)); + this.cdf = cumsum(this.pdf); + } + + /** + * Returns the distribution size + */ + public final int size() { + return this.pdf.length; + } + + /** + * Extract a random variable from to the distribution. + * + * The returned value is in the range [0..n) where n is the size of the + * distribution. + * + * Complexity is O(log(n)). + * + * @return A random variable + */ + public final int random() { + return lbound(cdf, Math.random()); + } + + /** + * Returns the arg min{x : array[x] >= value} + * + * Complexity is O(log(n)). + */ + private static int lbound(double[] array, double value) { + int lo = 0; + int hi = array.length - 1; + while (lo <= hi) { + int mid = (lo + hi) >> 1; + double x = array[mid]; + + if (x < value) { + lo = mid + 1; + } else if (x > value) { + hi = mid - 1; + } else { + return mid; + } + } + return lo; + } + + /** + * Check the values of the pdf function are ok. + */ + private static double[] check(double[] pdf) { + double min = Arrays.min(pdf); + if (min < 0) { + throw new IllegalArgumentException("pdf contains values < 0"); + } + + double max = Arrays.max(pdf); + if (max == 0) { + throw new IllegalArgumentException("pdf contains no nonzero values"); + } + + return pdf; + } + + /** + * Normalize the pdf function so that it sums to 1. + */ + private static double[] normalize(double[] pdf) { + double[] result = new double[pdf.length]; + + double sum = Arrays.sum(pdf); + for (int i = 0; i < pdf.length; i++) { + result[i] = pdf[i] / sum; + } + + return result; + } + + /** + * Calculate the cumulative sum of the array. + */ + private static double[] cumsum(double[] array) { + double[] result = new double[array.length]; + + double sum = 0.0; + for (int i = 0; i < array.length; i++) { + sum += array[i]; + result[i] = sum; + } + + return result; + } + + public static void main(String[] args) { + + double[] pdf = normal(5); //{1,2,3,4,5,4,5,3,2,1}; + InversionMethod var = new InversionMethod(pdf); + int[] variables = new int[10000]; + for (int i = 0; i < variables.length; i++) { + variables[i] = var.random(); + } + plothist("Normal Distribution", variables); + } + + public static double[] normal(int n) { + double[] result = new double[2*n+1]; + double sigma = n / 3.0; + System.out.println(sigma); + double scalef = 1.0 / (Math.sqrt(2.0*Math.PI) * sigma); + double denom = 2*sigma*sigma; + + for (int i = -n; i <= n; i++) { + result[i+n] = scalef * Math.exp(-(i*i)/denom); + } + return result; + } + + + private static JFrame plothist(String title, int[] values) { + final int[] hist = histogram(values); + final Color[] colors = new Color[hist.length]; + for (int i = 0; i < colors.length; i++) { + float r = (float) Math.random(); + float g = (float) Math.random(); + float b = (float) Math.random(); + colors[i] = new Color(r,g,b); + } + + + JFrame frame = new JFrame(title); + JPanel panel = new JPanel() { + private static final long serialVersionUID = 1L; + public void paint(Graphics graphics) { + Graphics2D g = (Graphics2D) graphics; + FontMetrics fontMetrics = g.getFontMetrics(); + + double w = getWidth(); + double h = getHeight(); + double spaceAtBottom = fontMetrics.getHeight() + 4; + double spaceAtTop = 3; + double spaceBetweenBars = 5; + + g.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON); + g.setRenderingHint(KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_ON); + g.setRenderingHint(KEY_FRACTIONALMETRICS, VALUE_FRACTIONALMETRICS_ON); + + g.setColor(Color.white); + g.fill(new Rectangle2D.Double(0,0,w,h)); + g.setColor(Color.black); + g.draw(new Line2D.Double(0,h-spaceAtBottom,w,h-spaceAtBottom)); + + double hmax = Arrays.max(hist); + double hcount = hist.length; + double space = w / hcount; + + Rectangle2D.Double bar = new Rectangle2D.Double(0,0,0,0); + + for (int i = 0; i < hist.length; i++) { + bar.x = i * space + spaceBetweenBars / 2; + bar.width = space - spaceBetweenBars; + bar.height = (h-(spaceAtBottom+spaceAtTop)) * (hist[i] / hmax); + bar.y = h - bar.height - spaceAtBottom; + g.setColor(colors[i]); + g.fill(bar); + g.setColor(Color.black); + g.draw(bar); + + String text = String.valueOf(hist[i]); + Rectangle2D bounds = fontMetrics.getStringBounds(text, g); + double tx = bar.getCenterX() - bounds.getWidth() / 2.0; + double ty = bar.getMinY() + bounds.getHeight() + 1; + if (ty > h - spaceAtBottom - 1) { + // place over the bar + ty = bar.getMinY() - 2; + } + g.drawString(text, (int) tx, (int) ty); + + text = String.valueOf(i); + bounds = fontMetrics.getStringBounds(text, g); + tx = bar.getCenterX() - bounds.getWidth() / 2.0; + ty = bar.getMaxY() + bounds.getHeight(); + g.drawString(text, (int) tx, (int) ty); + } + } + + public Dimension getPreferredSize() { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + int w = 50 * hist.length; + int h = 400; + w = Math.min(Math.max(w, 100), screenSize.width); + h = Math.min(h, screenSize.height); + return new Dimension(w,h); + } + }; + + frame.setLayout(new BorderLayout()); + frame.add(panel); + frame.pack(); + frame.setLocationRelativeTo(frame); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + return frame; + } + + private static int[] histogram(int[] values) { + int[] bins = new int[Arrays.max(values)+1]; + java.util.Arrays.fill(bins, 0); + for (int i = 0; i < values.length; i++) { + bins[values[i]]++; + } + return bins; + } +} diff --git a/Annotation/src/ie/dcu/swt/CocoaUIEnhancer$1.class b/Annotation/src/ie/dcu/swt/CocoaUIEnhancer$1.class new file mode 100644 index 0000000..73a5ef6 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/CocoaUIEnhancer$1.class differ diff --git a/Annotation/src/ie/dcu/swt/CocoaUIEnhancer$2.class b/Annotation/src/ie/dcu/swt/CocoaUIEnhancer$2.class new file mode 100644 index 0000000..b1c0f13 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/CocoaUIEnhancer$2.class differ diff --git a/Annotation/src/ie/dcu/swt/CocoaUIEnhancer.class b/Annotation/src/ie/dcu/swt/CocoaUIEnhancer.class new file mode 100644 index 0000000..3665245 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/CocoaUIEnhancer.class differ diff --git a/Annotation/src/ie/dcu/swt/CocoaUIEnhancer.java b/Annotation/src/ie/dcu/swt/CocoaUIEnhancer.java new file mode 100644 index 0000000..0903932 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/CocoaUIEnhancer.java @@ -0,0 +1,288 @@ +package ie.dcu.swt; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.eclipse.jface.action.IAction; +import org.eclipse.swt.SWT; +import org.eclipse.swt.internal.C; +import org.eclipse.swt.internal.Callback; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Listener; + +/** + * Provide a hook to connecting the Preferences, About and Quit menu items of + * the Mac OS X Application menu when using the SWT Cocoa bindings. + *

+ * This code does not require the Cocoa SWT JAR in order to be compiled as it + * uses reflection to access the Cocoa specific API methods. It does, however, + * depend on JFace (for IAction), but you could easily modify the code to use + * SWT Listeners instead in order to use this class in SWT only applications. + *

+ */ +public class CocoaUIEnhancer { + + private static final int kAboutMenuItem = 0; + private static final int kPreferencesMenuItem = 2; + private static final int kQuitMenuItem = 10; + + static long sel_toolbarButtonClicked_; + static long sel_preferencesMenuItemSelected_; + static long sel_aboutMenuItemSelected_; + + static Callback proc3Args; + + private final String appName; + + /** + * Construct a new CocoaUIEnhancer. + * + * @param appName + * The name of the application. It will be used to customize the + * About and Quit menu items. If you do not wish to customize the + * About and Quit menu items, just pass null here. + */ + public CocoaUIEnhancer(String appName) { + this.appName = appName; + } + + /** + * Hook the given Listener to the Mac OS X application Quit menu and the + * IActions to the About and Preferences menus. + * + * @param display + * The Display to use. + * @param quitListener + * The listener to invoke when the Quit menu is invoked. + * @param aboutAction + * The action to run when the About menu is invoked. + * @param preferencesAction + * The action to run when the Preferences menu is invoked. + */ + public void hookApplicationMenu(Display display, Listener quitListener, + final IAction aboutAction, final IAction preferencesAction) { + Object target = new Object() { + + // For the 32 bit JVM + @SuppressWarnings("unused") + int actionProc(int id, int sel, int arg) { + return (int) actionProc((long) id, (long) sel, (long) arg); + } + + // For the 64 bit JVM + long actionProc(long id, long sel, long arg) { + if (sel == sel_aboutMenuItemSelected_) { + aboutAction.run(); + } else if (sel == sel_preferencesMenuItemSelected_) { + preferencesAction.run(); + } + return 99; + } + }; + + try { + // Initialize the menuItems. + initialize(target); + } catch (Exception e) { + throw new IllegalStateException(e); + } + + // Connect the quit/exit menu. + if (!display.isDisposed()) { + display.addListener(SWT.Close, quitListener); + } + + // Schedule disposal of callback object + display.disposeExec(new Runnable() { + public void run() { + invoke(proc3Args, "dispose"); + } + }); + } + + private void initialize(Object callbackObject) throws Exception { + + Class osCls = classForName("org.eclipse.swt.internal.cocoa.OS"); + + // Register names in objective-c. + if (sel_toolbarButtonClicked_ == 0) { + // sel_toolbarButtonClicked_ = registerName( osCls, "toolbarButtonClicked:" ); //$NON-NLS-1$ + sel_preferencesMenuItemSelected_ = registerName(osCls, + "preferencesMenuItemSelected:"); //$NON-NLS-1$ + sel_aboutMenuItemSelected_ = registerName(osCls, + "aboutMenuItemSelected:"); //$NON-NLS-1$ + } + + // Create an SWT Callback object that will invoke the actionProc method + // of our internal callbackObject. + proc3Args = new Callback(callbackObject, "actionProc", 3); //$NON-NLS-1$ + Method getAddress = Callback.class + .getMethod("getAddress", new Class[0]); + Object object = getAddress.invoke(proc3Args, (Object[]) null); + long proc3 = convertToLong(object); + if (proc3 == 0) { + SWT.error(SWT.ERROR_NO_MORE_CALLBACKS); + } + + Class nsmenuCls = classForName("org.eclipse.swt.internal.cocoa.NSMenu"); + Class nsmenuitemCls = classForName("org.eclipse.swt.internal.cocoa.NSMenuItem"); + Class nsstringCls = classForName("org.eclipse.swt.internal.cocoa.NSString"); + Class nsapplicationCls = classForName("org.eclipse.swt.internal.cocoa.NSApplication"); + + // Instead of creating a new delegate class in objective-c, + // just use the current SWTApplicationDelegate. An instance of this + // is a field of the Cocoa Display object and is already the target + // for the menuItems. So just get this class and add the new methods + // to it. + object = invoke(osCls, "objc_lookUpClass", + new Object[] { "SWTApplicationDelegate" }); + long cls = convertToLong(object); + + // Add the action callbacks for Preferences and About menu items. + invoke(osCls, "class_addMethod", new Object[] { wrapPointer(cls), + wrapPointer(sel_preferencesMenuItemSelected_), wrapPointer(proc3), + "@:@" }); //$NON-NLS-1$ + invoke(osCls, "class_addMethod", + new Object[] { wrapPointer(cls), + wrapPointer(sel_aboutMenuItemSelected_), wrapPointer(proc3), + "@:@" }); //$NON-NLS-1$ + + // Get the Mac OS X Application menu. + Object sharedApplication = invoke(nsapplicationCls, "sharedApplication"); + Object mainMenu = invoke(sharedApplication, "mainMenu"); + Object mainMenuItem = invoke(nsmenuCls, mainMenu, "itemAtIndex", + new Object[] { wrapPointer(0) }); + Object appMenu = invoke(mainMenuItem, "submenu"); + + // Create the About menu command + Object aboutMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex", + new Object[] { wrapPointer(kAboutMenuItem) }); + if (appName != null) { + Object nsStr = invoke(nsstringCls, "stringWith", + new Object[] { "About " + appName }); + invoke(nsmenuitemCls, aboutMenuItem, "setTitle", + new Object[] { nsStr }); + } + // Rename the quit action. + if (appName != null) { + Object quitMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex", + new Object[] { wrapPointer(kQuitMenuItem) }); + Object nsStr = invoke(nsstringCls, "stringWith", + new Object[] { "Quit " + appName }); + invoke(nsmenuitemCls, quitMenuItem, "setTitle", + new Object[] { nsStr }); + } + + // Enable the Preferences menuItem. + Object prefMenuItem = invoke(nsmenuCls, appMenu, "itemAtIndex", + new Object[] { wrapPointer(kPreferencesMenuItem) }); + invoke(nsmenuitemCls, prefMenuItem, "setEnabled", new Object[] { true }); + + // Set the action to execute when the About or Preferences menuItem is + // invoked. + // + // We don't need to set the target here as the current target is the + // SWTApplicationDelegate + // and we have registerd the new selectors on it. So just set the new + // action to invoke the + // selector. + invoke(nsmenuitemCls, prefMenuItem, "setAction", + new Object[] { wrapPointer(sel_preferencesMenuItemSelected_) }); + invoke(nsmenuitemCls, aboutMenuItem, "setAction", + new Object[] { wrapPointer(sel_aboutMenuItemSelected_) }); + } + + private long registerName(Class osCls, String name) + throws IllegalArgumentException, SecurityException, + IllegalAccessException, InvocationTargetException, + NoSuchMethodException { + Object object = invoke(osCls, "sel_registerName", new Object[] { name }); + return convertToLong(object); + } + + private long convertToLong(Object object) { + if (object instanceof Integer) { + Integer i = (Integer) object; + return i.longValue(); + } + if (object instanceof Long) { + Long l = (Long) object; + return l.longValue(); + } + return 0; + } + + private static Object wrapPointer(long value) { + Class PTR_CLASS = C.PTR_SIZEOF == 8 ? long.class : int.class; + if (PTR_CLASS == long.class) + return new Long(value); + else + return new Integer((int) value); + } + + private static Object invoke(Class clazz, String methodName, + Object[] args) { + return invoke(clazz, null, methodName, args); + } + + private static Object invoke(Class clazz, Object target, + String methodName, Object[] args) { + try { + Class[] signature = new Class[args.length]; + for (int i = 0; i < args.length; i++) { + Class thisClass = args[i].getClass(); + if (thisClass == Integer.class) + signature[i] = int.class; + else if (thisClass == Long.class) + signature[i] = long.class; + else if (thisClass == Byte.class) + signature[i] = byte.class; + else if (thisClass == Boolean.class) + signature[i] = boolean.class; + else + signature[i] = thisClass; + } + Method method = clazz.getMethod(methodName, signature); + return method.invoke(target, args); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + private Class classForName(String classname) { + try { + Class cls = Class.forName(classname); + return cls; + } catch (ClassNotFoundException e) { + throw new IllegalStateException(e); + } + } + + private Object invoke(Class cls, String methodName) { + return invoke(cls, methodName, (Class[]) null, (Object[]) null); + } + + private Object invoke(Class cls, String methodName, + Class[] paramTypes, Object... arguments) { + try { + Method m = cls.getDeclaredMethod(methodName, paramTypes); + return m.invoke(null, arguments); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + private Object invoke(Object obj, String methodName) { + return invoke(obj, methodName, (Class[]) null, (Object[]) null); + } + + private Object invoke(Object obj, String methodName, Class[] paramTypes, + Object... arguments) { + try { + Method m = obj.getClass().getDeclaredMethod(methodName, paramTypes); + return m.invoke(obj, arguments); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } +} \ No newline at end of file diff --git a/Annotation/src/ie/dcu/swt/CursorFactory.class b/Annotation/src/ie/dcu/swt/CursorFactory.class new file mode 100644 index 0000000..2ae4c07 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/CursorFactory.class differ diff --git a/Annotation/src/ie/dcu/swt/CursorFactory.java b/Annotation/src/ie/dcu/swt/CursorFactory.java new file mode 100644 index 0000000..bee86a7 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/CursorFactory.java @@ -0,0 +1,78 @@ +package ie.dcu.swt; + +import java.util.*; + +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * Create cursors. + * + * @author Kevin McGuinness + */ +public class CursorFactory { + + /** + * Create a cross-hair cursor. + * + * @return The newly created cursor. + */ + public static Cursor createCrosshairCursor() { + + // Size of cursor + final int s = 24; + + // Number of points in cursor + final int n = s*s; + + // Midpoint of cursor + final int m = s/2; + + // Color indices + final byte black = 1; + final byte light = 2; + final byte trans = 0; + + // Cursor array + byte[] cursor = new byte[n]; + + // Flood with transparency + Arrays.fill(cursor, (byte) 0); + + // Set crosshair pixels + for (int i = 0; i < s; i++) { + + // Choose color + byte color = (i == m-2 || i == m+2) ? light : black; + + // Set pixels + if (i < m-1 || i > m+1) { + int idx1 = i+m*s; + int idx2 = m+i*s; + cursor[idx1] = (byte) color; + cursor[idx2] = (byte) color; + } + } + + // Set center pixel + cursor[m+m*s] = black; + + // Create colors + RGB[] colors = new RGB[] { + new RGB(255,255,255), + new RGB(0,0,0), + new RGB(128,128,128) + }; + + // Create palette + PaletteData palette = new PaletteData(colors); + + // Create image + ImageData image = new ImageData(s, s, 4, palette); + image.transparentPixel = trans; + image.setPixels(0, 0, n, cursor, 0); + + // Create cursor + return new Cursor(Display.getCurrent(), image, s/2, s/2); + } +} diff --git a/Annotation/src/ie/dcu/swt/Dispatcher.class b/Annotation/src/ie/dcu/swt/Dispatcher.class new file mode 100644 index 0000000..f4123d5 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/Dispatcher.class differ diff --git a/Annotation/src/ie/dcu/swt/Dispatcher.java b/Annotation/src/ie/dcu/swt/Dispatcher.java new file mode 100644 index 0000000..ceeea48 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/Dispatcher.java @@ -0,0 +1,98 @@ +package ie.dcu.swt; + +import java.io.Serializable; +import java.lang.reflect.*; +import java.util.logging.*; + +import org.eclipse.swt.widgets.*; + +/** + * Dispatch simple method calls by reflection. + * + * @author Kevin McGuinness + */ +public class Dispatcher implements Serializable, Listener { + + /** + * Serialization UID + */ + private static final long serialVersionUID = -8518627659417915880L; + + /** + * Logger used to report errors. + */ + private static final Logger logger = Logger.getLogger("Dispatcher"); + + /** + * The target object. + */ + public final Object object; + + /** + * The target method. + */ + public final Method method; + + /** + * Create a dispatcher that calls the given method on the given object. The + * method should have no parameters. If a SecurityException or a + * NoSuchMethodException occurs when getting the Method object, then it is + * logged and wrapped in a RuntimeException and re-thrown. + * + * @param object + * The target object. + * @param method + * The method name. + * @throws RuntimeException + * If a SecurityException or NoSuchMethodException occurs. + */ + public Dispatcher(Object object, String method) + throws RuntimeException + { + try { + this.object = object; + this.method = object.getClass().getMethod(method); + } catch (SecurityException e) { + logger.log(Level.SEVERE, "Cannot get method by reflection", e); + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + logger.log(Level.SEVERE, "Method not found: " + method, e); + throw new RuntimeException(e); + } + } + + /** + * Invoke the method on the object by reflection. If any exception occurs in + * the invocation, it is logged, then wrapped in a RuntimeException and + * re-thrown. + * + * @return The result of the method invocation, or null if the method is + * void. + * + * @throws RuntimeException + * If any exception occurs in the invocation, it is wrapped in a + * RuntimeException and re-thrown. + */ + public Object invoke() { + try { + return method.invoke(object); + } catch (IllegalArgumentException e) { + logger.log(Level.SEVERE, "Error invoking method", e); + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + logger.log(Level.SEVERE, "Error invoking method", e); + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + logger.log(Level.WARNING, "Invocation target error", e); + throw new RuntimeException(e); + } + } + + /** + * Allows the dispatcher to be used as an SWT listener. The event and + * return value are ignored. + */ + public void handleEvent(Event event) { + invoke(); + } +} diff --git a/Annotation/src/ie/dcu/swt/EventDispatcher.class b/Annotation/src/ie/dcu/swt/EventDispatcher.class new file mode 100644 index 0000000..e9c40ca Binary files /dev/null and b/Annotation/src/ie/dcu/swt/EventDispatcher.class differ diff --git a/Annotation/src/ie/dcu/swt/EventDispatcher.java b/Annotation/src/ie/dcu/swt/EventDispatcher.java new file mode 100644 index 0000000..0b7b577 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/EventDispatcher.java @@ -0,0 +1,104 @@ +package ie.dcu.swt; + + +import java.io.Serializable; +import java.lang.reflect.*; +import java.util.logging.*; + +import org.eclipse.swt.widgets.*; + +/** + * Dispatches method calls that take an Event parameter by reflection. + * + * @author Kevin McGuinness + */ +public class EventDispatcher implements Serializable, Listener { + + /** + * Serialization UID. + */ + private static final long serialVersionUID = 7238671421599697388L; + + /** + * Logger used to report errors. + */ + private static final Logger logger = Logger.getLogger("Dispatcher"); + + /** + * The target object. + */ + public final Object object; + + /** + * The target method. + */ + public final Method method; + + /** + * Create an event dispatcher that calls the given method on the given + * object. The method must take a single Event parameter. If a + * SecurityException or a NoSuchMethodException occurs when getting the + * Method object, then it is logged and wrapped in a RuntimeException and + * re-thrown. + * + * @param object + * The target object. + * @param method + * The method name. + * @throws RuntimeException + * If a SecurityException or NoSuchMethodException occurs. + */ + public EventDispatcher(Object object, String method) + throws RuntimeException + { + try { + this.object = object; + this.method = object.getClass().getMethod(method, Event.class); + } catch (SecurityException e) { + logger.log(Level.SEVERE, "Cannot get method by reflection", e); + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + logger.log(Level.SEVERE, "Method not found: " + method, e); + throw new RuntimeException(e); + } + } + + /** + * Invoke the method on the object by reflection. If any exception occurs in + * the invocation, it is logged, then wrapped in a RuntimeException and + * re-thrown. + * + * @param event + * The event to pass to the method invocation. + * + * @return The result of the method invocation, or null if the method is + * void. + * + * @throws RuntimeException + * If any exception occurs in the invocation, it is wrapped in a + * RuntimeException and re-thrown. + */ + public Object invoke(Event event) throws RuntimeException { + try { + return method.invoke(object, event); + } catch (IllegalArgumentException e) { + logger.log(Level.SEVERE, "Error invoking method", e); + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + logger.log(Level.SEVERE, "Error invoking method", e); + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + logger.log(Level.WARNING, "Invocation target error", e); + throw new RuntimeException(e); + } + } + + /** + * Allows the dispatcher to be used as an SWT listener. The event is + * passed to the method and the return value is ignored. + */ + public void handleEvent(Event event) { + invoke(event); + } + +} diff --git a/Annotation/src/ie/dcu/swt/ImageControl$1.class b/Annotation/src/ie/dcu/swt/ImageControl$1.class new file mode 100644 index 0000000..59c4ce2 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/ImageControl$1.class differ diff --git a/Annotation/src/ie/dcu/swt/ImageControl$2.class b/Annotation/src/ie/dcu/swt/ImageControl$2.class new file mode 100644 index 0000000..3fc5551 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/ImageControl$2.class differ diff --git a/Annotation/src/ie/dcu/swt/ImageControl$3.class b/Annotation/src/ie/dcu/swt/ImageControl$3.class new file mode 100644 index 0000000..b2fa9dc Binary files /dev/null and b/Annotation/src/ie/dcu/swt/ImageControl$3.class differ diff --git a/Annotation/src/ie/dcu/swt/ImageControl$4.class b/Annotation/src/ie/dcu/swt/ImageControl$4.class new file mode 100644 index 0000000..ce55445 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/ImageControl$4.class differ diff --git a/Annotation/src/ie/dcu/swt/ImageControl.class b/Annotation/src/ie/dcu/swt/ImageControl.class new file mode 100644 index 0000000..22ca344 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/ImageControl.class differ diff --git a/Annotation/src/ie/dcu/swt/ImageControl.java b/Annotation/src/ie/dcu/swt/ImageControl.java new file mode 100644 index 0000000..ade7104 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/ImageControl.java @@ -0,0 +1,969 @@ +package ie.dcu.swt; + + +import ie.dcu.swt.event.*; + +import java.util.*; +import java.util.List; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.*; + +public class ImageControl extends Composite { + + /** + * Minimum allowed zoom level (5% of original). + */ + public static final float MIN_ZOOM = 0.05f; + + + /** + * Maximum allowed zoom level (1000% of original) + */ + public static final float MAX_ZOOM = 10.f; + + /** + * Default zoom in/out step (10%) + */ + public static final float DEFAULT_ZOOM_STEP = 0.1f; + + + /** + * Default zoom level (100%) + */ + public static final float DEFAULT_ZOOM = 1.0f; + + + /** + * Canvas where the image is drawn. + */ + private final Canvas canvas; + + + /** + * Scroll bars. + */ + private final ScrolledComposite scroller; + + + /** + * The images bounding rectangle (after scaling + translation). + */ + private final Rectangle bounds; + + + /** + * Listeners for zoom events. + */ + private final List listeners; + + + /** + * The original image. + */ + private ObservableImage image; + + + /** + * The scaled image instance. + */ + private Image scaled; + + + /** + * Current zoom level. + */ + private float scale; + + + /** + * Current zoom in/out step. + */ + private float scaleStep; + + + /** + * Flag to indicate that a black line border around the image + * should be painted. Default is true. + */ + private boolean drawBorder; + + + /** + * Cached original image bounding rectangle. + */ + private transient Rectangle cachedImageBounds; + + + /** + * Construct an image view. The style can be any style that a Composite can + * have. The parent may not be {@code null}. Although this class extends + * Composite, it does not make sense to set a layout on it or to add other + * widgets to it. + * + * @param parent + * The parent Composite. + * @param style + * Style constants. + */ + public ImageControl(Composite parent, int style) { + super(parent, style); + + // Fill entire composite + setLayout(new FillLayout()); + + // Create scroll bars (always shown) + scroller = new ScrolledComposite(this, SWT.H_SCROLL | SWT.V_SCROLL); + + // Create canvas (set no background for efficiency, we'll draw it ourselves) + canvas = new Canvas(scroller, SWT.NO_BACKGROUND); + + // Initial bounds is an empty rectangle + bounds = new Rectangle(0, 0, 0, 0); + + // Zoom listeners + listeners = new ArrayList(2); + + // Setup scroll bars + scroller.setExpandHorizontal(true); + scroller.setExpandVertical(true); + scroller.setContent(canvas); + + // Listen for paint events and repaint canvas + canvas.addPaintListener(new PaintListener() { + public void paintControl(PaintEvent e) { + paintCanvas(e.gc); + } + }); + + // Listen for resizes and handle appropriately + scroller.addControlListener(new ControlAdapter() { + public void controlResized(ControlEvent e) { + handleResize(); + } + }); + + // Listen for dispose event + this.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + handleDispose(); + } + }); + + // Set defaults + scale = DEFAULT_ZOOM; + scaleStep = DEFAULT_ZOOM_STEP; + drawBorder = true; + } + + + /** + * Called when the scroll area is resized + */ + protected void handleResize() { + repaint(); + } + + + /** + * Handle a dispose event. + */ + protected void handleDispose() { + // Throw away the scaled image + disposeScaledImage(); + } + + + /** + * Called when the canvas needs to be painted. + * + * @param gc + * The paint graphics context. + */ + protected void paintCanvas(GC gc) { + + // Determine the clip (visible canvas area) + Rectangle clip = getVisibleCanvasArea(); + + if (!hasImage()) { + // Fill background + gc.fillRectangle(clip); + + return; + } + + if (!hasScaledImage()) { + // Create a scaled version of the image + createScaledImage(); + } + + // Set the clip + gc.setClipping(clip); + + // Draw the scaled image + gc.drawImage(scaled, bounds.x, bounds.y); + + // Draw background + int tGap = bounds.y - clip.y; + int bGap = bounds.y + bounds.height - clip.y + clip.height; + int lGap = bounds.x - clip.x; + int rGap = bounds.x + bounds.width - clip.x + clip.width; + + if (bounds.height < clip.height) { + gc.fillRectangle(clip.x, clip.y, clip.width, tGap); + gc.fillRectangle(clip.x, bounds.y + bounds.height, clip.width, bGap); + } + + if (bounds.width < clip.width) { + gc.fillRectangle(clip.x, clip.y + tGap, lGap, bounds.height); + gc.fillRectangle(bounds.x + bounds.width, clip.y + tGap, + rGap, bounds.height); + } + + // Draw a border around the image + if (drawBorder) { + SwtUtils.setForeground(gc, SWT.COLOR_BLACK); + gc.drawRectangle(bounds.x-1, bounds.y-1, bounds.width+1, bounds.height+1); + } + } + + + /** + * Handles changes in the image data. + */ + protected void handleImageChanged(ImageEvent e) { + + // If dimensions changed, re-constructed entire scaled image + if (e.dimensionsChanged()) { + cachedImageBounds = null; + createScaledImage(); + return; + } + + + // If no scaled image available, construct one + if (!hasScaledImage()) { + recomputeBounds(); + + // Construct scaled image + scaled = new Image(getDisplay(), + bounds.width, bounds.height); + } + + Rectangle modified = + e.modified.intersection(getImageBounds()); + + // Scale modified rectangle + Rectangle target = + SwtUtils.scale(modified, scale); + + // Create graphics context + GC gc = new GC(scaled); + + // Set clip + gc.setClipping(target); + + // Redraw modified part + gc.drawImage( + image.getImage(), + modified.x, + modified.y, + modified.width, + modified.height, + target.x, + target.y, + target.width, + target.height + ); + + // Dispose graphics context + gc.dispose(); + + // Repaint canvas + repaint(modified); + } + + + /** + * Returns the properly scaled version of the current image, after zooming has + * been performed. Returns null if there is no current image. + * + * @return The scaled image, or null. + */ + public Image getScaledImage() { + if (!hasScaledImage()) { + createScaledImage(); + } + return scaled; + } + + + /** + * Get the current image. Returns {@code null} if there is none. + * + * @return The image, or null. + */ + public ObservableImage getImage() { + return image; + } + + + /** + * Set the currently displayed image. This method has no effect if the given + * image is the same as the currently displayed one. Otherwise, the image is + * set to the new one, the zoom is reset to 1.0 and the control is repainted. + * The given image may also be {@code null} to clear the display to its + * background color. + * + *

Note: The old image is not disposed of. + * + * @param image + * The image, or null. + */ + public void setImage(ObservableImage image) { + if (this.image != image) { + // Dispose of scaled image + disposeScaledImage(); + + // Remove old listener + if (this.image != null) { + this.image.removeImageListener(imageListener); + } + + // Set image + this.image = image; + + // Add new listener + if (this.image != null) { + this.image.addImageListener(imageListener); + } + + // Invalidate cached bounds + this.cachedImageBounds = null; + + // Reset scale + this.scale = 1.0f; + + // Repaint + repaint(); + } + } + + + /** + * Set flag to indicate that a black line border around the image will be + * drawn. Will repaint if changed. + * + * @param drawBorder + * true to draw a border. + */ + public void setDrawBorder(boolean drawBorder) { + if (this.drawBorder != drawBorder) { + this.drawBorder = drawBorder; + repaint(); + } + } + + + /** + * Returns true if the drawBorder flag is set. + * + * @return true if a black border around the image will be + * drawn. + * @see ImageControl#setDrawBorder(boolean) + */ + public boolean getDrawBorder() { + return drawBorder; + } + + + + /** + * Returns {@code true} if the view has an image and it has not been disposed. + * + * @return true if view has an image + */ + public boolean hasImage() { + return image != null && !image.isDisposed(); + } + + + /** + * Set the currently displayed image. This method has no effect if the given + * image is the same as the currently displayed one. Otherwise, the image is + * set to the new one, the zoom is reset to 1.0 and the control is repainted. + * The given image may also be {@code null} to clear the display to its + * background color. + * + * @param image + * The image, or null. + * @param disposeOld + * If true the old image is disposed of before + * changing. But only if the passed image is not the same as the old + * one. + */ + public void setImage(ObservableImage image, boolean disposeOld) { + if (this.image != image) { + if (this.image != null && disposeOld) { + this.image.dispose(); + } + setImage(image); + } + } + + + /** + * Returns the current zoom level, which will always be between MIN_ZOOM and + * MAX_ZOOM. A zoom level of 1.0 is the original size. + * + * @return The zoom level. + */ + public float getZoom() { + return scale; + } + + + /** + * Set the zoom level. The value given must be between MIN_ZOOM and MAX_ZOOM. + * If the zoom level is different from the current zoom level, the zoom level + * is updated and the image is repainted at the new zoom level. + * + * @param zoom + * The zoom level to set. + */ + public void setZoom(float zoom) { + if (this.scale != zoom) { + if (zoom < MIN_ZOOM) { + throw new IllegalArgumentException("zoom < MIN_ZOOM"); + } + + if (zoom > MAX_ZOOM) { + throw new IllegalArgumentException("zoom > MAX_ZOOM"); + } + + disposeScaledImage(); + this.scale = zoom; + + repaint(); + + // Notify listeners + fireZoomChanged(); + } + } + + + /** + * Returns the current zoom step, i.e. the amount of zoom change that will be + * caused by a zoom in or zoom out operation. + * + * @return The current zoom step. + */ + public float getZoomStep() { + return scaleStep; + } + + + /** + * Set the current zoom step, i.e. the amount of zoom change that will be + * caused by a zoom in or zoom out operation. + * + * @param zoomStep + * The new zoom step (must be {@code > 0}). + */ + public void setZoomStep(float zoomStep) { + if (zoomStep < 0) { + throw new IllegalArgumentException("zoomStep < 0"); + } + + this.scaleStep = zoomStep; + } + + + /** + * Zoom in using the current zoom step. This method will never allow the zoom + * to be greater than MAX_ZOOM. + */ + public void zoomIn() { + if (image != null) { + float zoom = Math.min(MAX_ZOOM, scale + scaleStep); + setZoom(zoom); + } + } + + + /** + * Zoom in using the current zoom step. This method will never allow the zoom + * to be less than MIN_ZOOM. + */ + public void zoomOut() { + if (image != null) { + float zoom = Math.max(MIN_ZOOM, scale - scaleStep); + setZoom(zoom); + } + } + + + /** + * Zoom the image back to it's original size. + */ + public void zoomOriginal() { + setZoom(1.0f); + } + + + /** + * Zoom the image to it's best fit inside the currently visible scroll area. + * The aspect ratio is maintained. + */ + public void zoomBestFit() { + if (image != null) { + float zoom = getBestFitScale(); + setZoom(zoom); + } + } + + + /** + * Returns true if calling {@link ImageControl#zoomIn()} will have + * an effect. + * + * @return true if zooming in is possible. + */ + public boolean canZoomIn() { + if (image != null) { + float zoom = Math.min(MAX_ZOOM, scale + scaleStep); + return zoom != scale; + } + return false; + } + + + /** + * Returns true if calling {@link ImageControl#zoomOut()} will + * have an effect. + * + * @return true if zooming out is possible. + */ + public boolean canZoomOut() { + if (image != null) { + float zoom = Math.max(MIN_ZOOM, scale - scaleStep); + return zoom != scale; + } + return false; + } + + + /** + * Returns true if calling {@link ImageControl#zoomOriginal()} + * will have an effect. + * + * @return true if zooming to the original size will change the + * zoom level. + */ + public boolean canZoomOriginal() { + if (image != null) { + return scale != 1.0; + } + return false; + } + + + /** + * Returns true if calling {@link ImageControl#zoomBestFit()} will + * have an effect. + * + * @return true if zooming to the "best-fit" will change the + * zoom level. + */ + public boolean canZoomBestFit() { + if (image != null) { + return scale != getBestFitScale(); + } + return false; + } + + + /** + * Force the visible canvas area to repaint itself. + */ + public void repaint() { + recomputeBounds(); + Rectangle r = getVisibleCanvasArea(); + canvas.redraw(r.x, r.y, r.width, r.height, false); + } + + + /** + * Force the given part of the image to repaint itself. The image rectangle is + * automatically scaled and translated to canvas coordinates. If the image is + * null, then the function does nothing. + * + * @param part + * The part of the image repaint. + */ + public void repaint(Rectangle part) { + if (image != null) { + recomputeBounds(); + Rectangle canv = imageToCanvas(part); + Rectangle clip = getVisibleCanvasArea().intersection(canv); + canvas.redraw(clip.x, clip.y, clip.width, clip.height, false); + } + } + + + /** + * Returns {@code true} if the given point on the canvas is contained within + * the area covered by the image displayed on the canvas. If there is no + * image, returns {@code false} + * + * @param canvasPt + * A point in canvas coordinates. + * @return true if contained in the image. + */ + public boolean imageContains(Point canvasPt) { + if (image != null) { + return bounds.contains(canvasPt); + } + return false; + } + + + + /** + * Translate a point on the canvas to it's corresponding point on the image + * currently that is displayed on the canvas. If there is no current image + * set, an {@code IllegalStateException} is thrown. The returned point is at + * the original image's scale. + * + * @param pt + * The point to translate. + * @return The corresponding point on the image. + */ + public Point canvasToImage(Point pt) { + checkHaveImage(); + + // translate to image (0,0) + int x = pt.x - bounds.x; + int y = pt.y - bounds.y; + + // scale + x = (int) Math.floor(x / scale); + y = (int) Math.floor(y / scale); + + return new Point(x, y); + } + + + /** + * Translate a point on the displayed image (at it's original scale) to the + * corresponding point on the canvas. If there is no current image set, an + * {@code IllegalStateException} is thrown. + * + * @param pt + * The point on the canvas. + * @return The corresponding point on the image. + */ + public Point imageToCanvas(Point pt) { + checkHaveImage(); + + // scale + int x = (int) Math.floor(pt.x * scale); + int y = (int) Math.floor(pt.y * scale); + + // translate + x += bounds.x; + y += bounds.y; + + return new Point(x, y); + } + + + /** + * Translates a rectangle on the image to a rectangle on the canvas. If there + * is no current image set, an {@code IllegalStateException} is thrown. If the + * given rectangle lies outside the image, only the part that lies inside the + * canvas image bounds is returned (the intersection). If it is completely + * outside the canvas image bounds, an empty rectangle is returned. + * + * @param rect + * The rectangle to translate. + * @return The translated rectangle. + */ + public Rectangle imageToCanvas(Rectangle rect) { + checkHaveImage(); + + int x = (int) Math.floor(rect.x * scale) + bounds.x; + int y = (int) Math.floor(rect.y * scale) + bounds.y; + int w = (int) Math.floor(rect.width * scale); + int h = (int) Math.floor(rect.height * scale); + + return new Rectangle(x, y, w, h).intersection(bounds); + } + + + /** + * Translate a rectangle on the canvas to a rectangle on the image. If there + * is no current image set, an {@code IllegalStateException} is thrown. + * + * @param rect + * The rectangle to translate. + * @return The translated rectangle. + */ + public Rectangle canvasToImage(Rectangle rect) { + checkHaveImage(); + + int x = (int) Math.floor((rect.x - bounds.x) / scale); + int y = (int) Math.floor((rect.y - bounds.y) / scale); + int w = (int) Math.floor(rect.width / scale); + int h = (int) Math.floor(rect.height / scale); + + return new Rectangle(x, y, w, h); + } + + + /** + * Get the canvas that the image is drawn on. + * + * @return The canvas. + */ + public Canvas getCanvas() { + return canvas; + } + + + /** + * Convenience method to set the canvas background color. + * + * @param color + * The color to set. + */ + public void setCanvasBackground(Color color) { + canvas.setBackground(color); + } + + + + /** + * Returns the bounds of the original image, or null if there + * is no image. + * + * @return The bounding rectangle of the image, or null. + */ + public Rectangle getImageBounds() { + + if (cachedImageBounds == null) { + if (image != null) { + cachedImageBounds = image.getBounds(); + } + } + return cachedImageBounds; + } + + + /** + * Returns the bounds of the image, as currently displayed on the canvas. This + * is the original image bounds, translated and scaled onto the image canvas. + * Returns null if there is no set image. + * + * @return The canvas image bounds, or null. + */ + public Rectangle getCanvasImageBounds() { + return bounds; + } + + + /** + * Add a zoom listener. + * + * @param listener + * The listener to add. + */ + public void addZoomListener(ZoomListener listener) { + listeners.add(listener); + } + + + /** + * Remove a zoom listener. + * + * @param listener + * The listener to remove. + */ + public void removeZoomListener(ZoomListener listener) { + listeners.remove(listener); + } + + + /** + * Dispose of the old scaled image (hence invalidating it). + */ + public void disposeScaledImage() { + if (scaled != null) { + if (!scaled.isDisposed()) { + scaled.dispose(); + } + scaled = null; + } + } + + + + /** + * Returns the scale of the "best-fit" for the currently visible scroll area, + * maintaining the aspect ratio and staying within the MAX_ZOOM and MIN_ZOOM + * bounds. + * + * @return The best fit scale. + */ + private float getBestFitScale() { + Rectangle client = scroller.getClientArea(); + Rectangle imrect = getImageBounds(); + + float sx = client.width / (float) imrect.width; + float sy = client.height / (float) imrect.height; + + float zoom = Math.min(sx, sy); + if (zoom > MAX_ZOOM) zoom = MAX_ZOOM; + if (zoom < MIN_ZOOM) zoom = MIN_ZOOM; + return zoom; + } + + + /** + * Disposes of any old scaled image and constructs a new one. + */ + private void createScaledImage() { + disposeScaledImage(); + + if (hasImage()) { + recomputeBounds(); + + scaled = new Image(getDisplay(), bounds.width, bounds.height); + + GC gc = new GC(scaled); + + Rectangle r = getImageBounds(); + gc.drawImage(image.getImage(), + 0, 0, r.width, r.height, + 0, 0, bounds.width, bounds.height + ); + + gc.dispose(); + } + } + + + /** + * Computes and returns the region on the canvas that is currently visible + * in the scroll pane. + * + * @return The visible canvas area. + */ + private Rectangle getVisibleCanvasArea() { + Rectangle clip = scroller.getClientArea(); + Point scrollPos = getScrollbarPosition(); + clip.x += scrollPos.x; + clip.y += scrollPos.y; + return clip; + } + + + /** + * Get the horizontal and vertical scroll-bar positions. + * + * @return the scroll-bar position. + */ + private Point getScrollbarPosition() { + int sx = scroller.getHorizontalBar().getSelection(); + int sy = scroller.getVerticalBar().getSelection(); + return new Point(sx, sy); + } + + + /** + * Recompute the canvas image bounds and update the scroll bars. + */ + private void recomputeBounds() { + + if (image == null) { + // No image + scroller.setMinSize(0,0); + bounds.x = bounds.y = 0; + bounds.width = bounds.height = 0; + return; + } + + Rectangle imrect = getImageBounds(); + Rectangle area = scroller.getClientArea(); + + // Scale image width and height + bounds.width = (int) (imrect.width * scale); + bounds.height = (int) (imrect.height * scale); + + // Center image horizontally + if (bounds.width < area.width) { + int dx = area.width - bounds.width; + bounds.x = dx / 2; + } else { + bounds.x = 0; + } + + // Center image vertically + if (bounds.height < area.height) { + int dy = area.height - bounds.height; + bounds.y = dy / 2; + } else { + bounds.y = 0; + } + + // Configure scroll bars + scroller.setMinSize(bounds.width, bounds.height); + } + + + /** + * Returns true if we have an up to date copy of a properly + * scaled version of the image. + * + * @return true if a scaled image is available. + */ + private boolean hasScaledImage() { + return scaled != null && !scaled.isDisposed(); + } + + + /** + * Throws an {@code IllegalStateException} if there is no image. + */ + private void checkHaveImage() { + if (image == null) { + throw new IllegalStateException("image == null"); + } + } + + + /** + * Fire a zoom changed event. + */ + private void fireZoomChanged() { + ZoomEvent evt = null; + for (ZoomListener z : listeners) { + if (evt == null) { + evt = new ZoomEvent(this); + } + z.zoomChanged(evt); + } + } + + + private ImageListener imageListener = new ImageListener() { + public void imageChanged(ImageEvent e) { + handleImageChanged(e); + } + }; + +} diff --git a/Annotation/src/ie/dcu/swt/ImageConverter.class b/Annotation/src/ie/dcu/swt/ImageConverter.class new file mode 100644 index 0000000..ef75a11 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/ImageConverter.class differ diff --git a/Annotation/src/ie/dcu/swt/ImageConverter.java b/Annotation/src/ie/dcu/swt/ImageConverter.java new file mode 100644 index 0000000..ccb037f --- /dev/null +++ b/Annotation/src/ie/dcu/swt/ImageConverter.java @@ -0,0 +1,172 @@ +package ie.dcu.swt; + +import java.awt.image.*; + +import org.eclipse.swt.graphics.*; + +/** + * Converts SWT ImageData objects to BufferedImage objects and vice-versa. + * + * @author Kevin McGuinness + */ +public class ImageConverter { + + public static BufferedImage convert(ImageData data) { + ColorModel cm = null; + PaletteData palette = data.palette; + + if (palette.isDirect) { + cm = new DirectColorModel( + data.depth, + palette.redMask, + palette.greenMask, + palette.blueMask + ); + + WritableRaster raster = cm.createCompatibleWritableRaster( + data.width, data.height); + + BufferedImage im = new BufferedImage(cm, raster, false, null); + + int[] pixels = new int[3]; + for (int y = 0; y < data.height; y++) { + for (int x = 0; x < data.width; x++) { + int pixel = data.getPixel(x, y); + RGB rgb = palette.getRGB(pixel); + pixels[0] = rgb.red; + pixels[1] = rgb.green; + pixels[2] = rgb.blue; + raster.setPixels(x, y, 1, 1, pixels); + } + } + return im; + + } else { + + RGB[] rgbs = palette.getRGBs(); + byte[] red = new byte[rgbs.length]; + byte[] green = new byte[rgbs.length]; + byte[] blue = new byte[rgbs.length]; + + for (int i = 0; i < rgbs.length; i++) { + RGB rgb = rgbs[i]; + red[i] = (byte) rgb.red; + green[i] = (byte) rgb.green; + blue[i] = (byte) rgb.blue; + } + + if (data.transparentPixel != -1) { + cm = new IndexColorModel( + data.depth, + rgbs.length, + red, green, blue, + data.transparentPixel + ); + + } else { + cm = new IndexColorModel( + data.depth, + rgbs.length, + red, green, blue + ); + } + + WritableRaster raster = cm.createCompatibleWritableRaster( + data.width, data.height); + + BufferedImage im = new BufferedImage(cm, + raster, false, null); + + int[] pixels = new int[1]; + for (int y = 0; y < data.height; y++) { + for (int x = 0; x < data.width; x++) { + int pixel = data.getPixel(x, y); + pixels[0] = pixel; + raster.setPixel(x, y, pixels); + } + } + + return im; + } + } + + + public static ImageData convertToSWT(BufferedImage im) { + + ColorModel cm = im.getColorModel(); + + if (cm instanceof DirectColorModel) { + DirectColorModel dcm = (DirectColorModel) cm; + + PaletteData palette = new PaletteData( + dcm.getRedMask(), + dcm.getGreenMask(), + dcm.getBlueMask() + ); + + ImageData data = new ImageData( + im.getWidth(), im.getHeight(), + dcm.getPixelSize(), palette + ); + + WritableRaster raster = im.getRaster(); + + int[] pixels = new int[3]; + RGB rgb = new RGB(0,0,0); + + for (int y = 0; y < data.height; y++) { + for (int x = 0; x < data.width; x++) { + raster.getPixel(x, y, pixels); + rgb.red = pixels[0]; + rgb.green = pixels[1]; + rgb.blue = pixels[2]; + int pixel = palette.getPixel(rgb); + data.setPixel(x, y, pixel); + } + } + + return data; + + + } else if (cm instanceof IndexColorModel) { + IndexColorModel icm = (IndexColorModel) cm; + + int size = icm.getMapSize(); + byte[] reds = new byte[size]; + byte[] greens = new byte[size]; + byte[] blues = new byte[size]; + + icm.getReds(reds); + icm.getGreens(greens); + icm.getBlues(blues); + + RGB[] rgbs = new RGB[size]; + for (int i = 0; i < rgbs.length; i++) { + rgbs[i] = new RGB(reds[i] & 0xFF, greens[i] & 0xFF, blues[i] & 0xFF); + } + + PaletteData palette = new PaletteData(rgbs); + + ImageData data = new ImageData( + im.getWidth(), im.getHeight(), + icm.getPixelSize(), palette + ); + + + data.transparentPixel = icm.getTransparentPixel(); + WritableRaster raster = im.getRaster(); + + int[] pixels = new int[1]; + for (int y = 0; y < data.height; y++) { + for (int x = 0; x < data.width; x++) { + raster.getPixel(x, y, pixels); + data.setPixel(x, y, pixels[0]); + } + } + + return data; + } + + return null; + } +} diff --git a/Annotation/src/ie/dcu/swt/MatrixVisualizer.class b/Annotation/src/ie/dcu/swt/MatrixVisualizer.class new file mode 100644 index 0000000..865e373 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/MatrixVisualizer.class differ diff --git a/Annotation/src/ie/dcu/swt/MatrixVisualizer.java b/Annotation/src/ie/dcu/swt/MatrixVisualizer.java new file mode 100644 index 0000000..ba12aa8 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/MatrixVisualizer.java @@ -0,0 +1,74 @@ +package ie.dcu.swt; + +import ie.dcu.image.colormap.*; +import ie.dcu.matrix.*; + +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.PaletteData; + +/** + * Visualize matrices using color maps. + * + * @author Kevin McGuinness + */ +public class MatrixVisualizer { + + private ColorMap colorMap; + + public MatrixVisualizer() { + this(ColorMaps.hot()); + } + + public MatrixVisualizer(ColorMap map) { + setColorMap(map); + } + + public ColorMap getColorMap() { + return colorMap; + } + + public void setColorMap(ColorMap map) { + if (map == null) { + throw new IllegalArgumentException("colorMap == null"); + } + this.colorMap = map; + } + + public ImageData createVisualization(Matrix matrix) { + return visualize(matrix.toDoubleMatrix()); + } + + private ImageData visualize(DoubleMatrix matrix) { + rescale(matrix); + PaletteData palette = colorMap.createPaletteData(); + ImageData image = new ImageData(matrix.cols, matrix.rows, 8, palette); + + int n = colorMap.size(); + + for (int i = 0; i < matrix.rows; i++) { + int k = i * matrix.cols; + + for (int j = 0; j < matrix.cols; j++, k++) { + int value = (int) (matrix.values[k] * (n-1)); + image.setPixel(j, i, value); + } + } + + return image; + } + + private void rescale(DoubleMatrix matrix) { + + double min = matrix.minValue(); + double max = matrix.maxValue(); + double range = max - min; + + if (range == 0) { + range = 1; + } + + for (int i = 0; i < matrix.size; i++) { + matrix.values[i] = (matrix.values[i] + min) / range; + } + } +} diff --git a/Annotation/src/ie/dcu/swt/ObservableImage.class b/Annotation/src/ie/dcu/swt/ObservableImage.class new file mode 100644 index 0000000..071b336 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/ObservableImage.class differ diff --git a/Annotation/src/ie/dcu/swt/ObservableImage.java b/Annotation/src/ie/dcu/swt/ObservableImage.java new file mode 100644 index 0000000..fd002ab --- /dev/null +++ b/Annotation/src/ie/dcu/swt/ObservableImage.java @@ -0,0 +1,187 @@ +package ie.dcu.swt; + +import ie.dcu.swt.event.*; + +import java.util.*; + +import org.eclipse.swt.graphics.*; + +public class ObservableImage { + private final List listeners; + private Image image; + private ImageData data; + private Rectangle modified; + private GC gc; + private int refCount; + private boolean suspendNotifications; + + + public ObservableImage(Image image) { + this.listeners = new ArrayList(2); + this.image = image; + } + + + public GC beginPaint() { + if (refCount > 0) { + refCount++; + return gc; + } else { + modified = null; + refCount = 1; + return (gc = new GC(image)); + } + } + + + public void endPaint() { + endPaint(null); + } + + + public void endPaint(Rectangle modified) { + refCount--; + if (refCount < 0) { + throw new IllegalStateException(); + } + + updateModified(modified); + + if (refCount == 0) { + data = null; + gc.dispose(); + gc = null; + fireImageChanged(); + } + } + + + public Image getImage() { + return image; + } + + + public ImageData getImageData() { + if (data == null) { + data = image.getImageData(); + } + return data; + } + + + public void setImage(Image image, boolean disposeOld) { + if (gc != null) { + throw new IllegalStateException(); + } + + if (image == null) { + throw new NullPointerException(); + } + + boolean dimensionsChanged = false; + if (this.image != null && !this.image.isDisposed()) { + Rectangle oldBounds = this.image.getBounds(); + Rectangle newBounds = image.getBounds(); + + dimensionsChanged = !oldBounds.equals(newBounds); + } else { + dimensionsChanged = true; + } + + if (disposeOld) { + dispose(); + } + + this.image = image; + + // Invalidate cached image data + this.data = null; + fireImageChanged(dimensionsChanged); + } + + + + public void setSuspendNotifications(boolean suspend) { + this.suspendNotifications = suspend; + } + + + public boolean isDisposed() { + if (image != null) { + return image.isDisposed(); + } + return false; + } + + + public void dispose() { + if (image != null && !image.isDisposed()) { + image.dispose(); + } + data = null; + } + + + public Rectangle getBounds() { + return image.getBounds(); + } + + + public Rectangle getModifiedArea() { + return modified; + } + + + public void addImageListener(ImageListener listener) { + listeners.add(listener); + } + + + public void removeImageListener(ImageListener listener) { + listeners.remove(listener); + } + + + public void fireImageChanged() { + fireImageChanged(getModifiedArea(), false); + } + + + public void fireImageChanged(Rectangle modified) { + fireImageChanged(modified, false); + } + + + private void fireImageChanged(boolean dimensionsChanged) { + fireImageChanged(getModifiedArea(), dimensionsChanged); + } + + + private void fireImageChanged(Rectangle modified, boolean dimensionsChanged) { + if (suspendNotifications) { + return; + } + + ImageEvent e = null; + for (ImageListener i : listeners) { + if (e == null) { + e = new ImageEvent(this, modified, dimensionsChanged); + } + i.imageChanged(e); + } + } + + + private void updateModified(Rectangle m) { + if (m == null) { + this.modified = image.getBounds(); + } else { + if (this.modified != null) { + this.modified = this.modified.union(m); + } else { + this.modified = SwtUtils.clone(m); + } + } + } +} + diff --git a/Annotation/src/ie/dcu/swt/PopupComposite$1.class b/Annotation/src/ie/dcu/swt/PopupComposite$1.class new file mode 100644 index 0000000..0e43546 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/PopupComposite$1.class differ diff --git a/Annotation/src/ie/dcu/swt/PopupComposite$ActivationListener.class b/Annotation/src/ie/dcu/swt/PopupComposite$ActivationListener.class new file mode 100644 index 0000000..f215e2f Binary files /dev/null and b/Annotation/src/ie/dcu/swt/PopupComposite$ActivationListener.class differ diff --git a/Annotation/src/ie/dcu/swt/PopupComposite.class b/Annotation/src/ie/dcu/swt/PopupComposite.class new file mode 100644 index 0000000..3e06dc4 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/PopupComposite.class differ diff --git a/Annotation/src/ie/dcu/swt/PopupComposite.java b/Annotation/src/ie/dcu/swt/PopupComposite.java new file mode 100644 index 0000000..90ba969 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/PopupComposite.java @@ -0,0 +1,200 @@ +package ie.dcu.swt; + +import org.eclipse.swt.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + + +/** + * Class for displaying a pop-up control in its own shell. The control behaves + * similar to a pop-up menu, but is a composite so can contain arbitrary + * controls. + * + *

+ * Sample Usage: + * + *

+ * PopupComposite popup = new PopupComposite(getShell());
+ * Text text = new Text(popup, SWT.BORDER);
+ * popup.pack();
+ * popup.show(shell.toDisplay(new Point(10, 10)));
+ * 
+ * + * @author Kevin McGuinness + */ +public class PopupComposite extends Composite { + + + /** + * Style of the shell that will house the composite + */ + private static final int SHELL_STYLE = + SWT.MODELESS | SWT.NO_TRIM | SWT.ON_TOP | SWT.BORDER; + + + /** + * Shell that will house the composite + */ + private final Shell shell; + + + /** + * Create a Pop-up composite with the default {@link SWT#BORDER} style. + * + * @param parent + * The parent shell. + */ + public PopupComposite(Shell parent) { + this(parent, SWT.BORDER); + } + + + /** + * Create a Pop-up composite. The default layout is a fill layout. + * + * @param parent + * The parent shell. + * @param style + * The composite style. + */ + public PopupComposite(Shell parent, int style) { + super(new Shell(parent, SHELL_STYLE), style); + shell = getShell(); + shell.setLayout(new FillLayout());; + shell.addShellListener(new ActivationListener()); + setLayout(createLayout()); + } + + + /** + * Display the composite below the given tool item. The item will be sized + * such that it's width is at least the width of the given tool item. + * + * @param bar + * The tool bar. + * @param item + * The tool item. + */ + public void showBelow(ToolBar bar, ToolItem item) { + Rectangle r = item.getBounds(); + Point p = bar.toDisplay(new Point(r.x, r.y + r.height)); + setSize(computeSize(item)); + show(p); + } + + + /** + * Display the composite in its own shell at the given point. + * + * @param pt + * The point where the pop-up should appear. + */ + public void show(Point pt) { + // Match shell and component sizes + shell.setSize(getSize()); + + if (pt != null) { + shell.setLocation(pt); + } + + shell.open(); + } + + + /** + * Display the pop-up where it was last displayed. + */ + public void show() { + show(null); + } + + + /** + * Hide the pop-up. + */ + public void hide() { + shell.setVisible(false); + } + + + /** + * Returns true if the shell is currently activated. + * + * @return true if the shell is visible. + */ + public boolean isDisplayed() { + return shell.isVisible(); + } + + + /** + * Creates the default layout for the composite. + * + * @return the default layout. + */ + private FillLayout createLayout() { + FillLayout layout = new FillLayout(); + layout.marginWidth = 5; + layout.marginHeight = 5; + return layout; + } + + + /** + * Computes the optimal size with respect to the given tool item. + * + * @param item + * The tool item. + * @return The optimal size. + */ + private Point computeSize(ToolItem item) { + Point s2 = computeSize(item.getWidth(), SWT.DEFAULT); + Point s1 = computeSize(SWT.DEFAULT, SWT.DEFAULT); + return s1.x > s2.x ? s1 : s2; + } + + + /** + * Class that handles shell appearance and disappearance appropriately. + * Specifically, it hides the shell when it becomes de-activated (for example, + * when the user clicks on the parent shell). Also, there is a minimum delay + * which is enforced between showing and hiding the pop-up, to prevent + * undesirable behavior such as hiding and immediately re-displaying the + * pop-up when the user selects a button responsible for showing the tool + * item. + */ + private final class ActivationListener extends ShellAdapter { + private static final int TIMEOUT = 500; + private long time = -1; + + + @Override + public void shellDeactivated(ShellEvent e) { + // Record time of event + time = (e.time & 0xFFFFFFFFL); + + // Hide + hide(); + } + + + @Override + public void shellActivated(ShellEvent e) { + if (time > 0) { + // Find elapsed time + long elapsed = ((e.time & 0xFFFFFFFFL) - time); + + // If less than a timeout, don't activate + if (elapsed < TIMEOUT) { + hide(); + + // Next activation event is fine + time = -1; + } + } + } + }; + +} \ No newline at end of file diff --git a/Annotation/src/ie/dcu/swt/SwtUtils$1.class b/Annotation/src/ie/dcu/swt/SwtUtils$1.class new file mode 100644 index 0000000..43392ad Binary files /dev/null and b/Annotation/src/ie/dcu/swt/SwtUtils$1.class differ diff --git a/Annotation/src/ie/dcu/swt/SwtUtils$Pt.class b/Annotation/src/ie/dcu/swt/SwtUtils$Pt.class new file mode 100644 index 0000000..e350637 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/SwtUtils$Pt.class differ diff --git a/Annotation/src/ie/dcu/swt/SwtUtils$Rect.class b/Annotation/src/ie/dcu/swt/SwtUtils$Rect.class new file mode 100644 index 0000000..6ba7425 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/SwtUtils$Rect.class differ diff --git a/Annotation/src/ie/dcu/swt/SwtUtils.class b/Annotation/src/ie/dcu/swt/SwtUtils.class new file mode 100644 index 0000000..f00e9a5 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/SwtUtils.class differ diff --git a/Annotation/src/ie/dcu/swt/SwtUtils.java b/Annotation/src/ie/dcu/swt/SwtUtils.java new file mode 100644 index 0000000..fd1d95e --- /dev/null +++ b/Annotation/src/ie/dcu/swt/SwtUtils.java @@ -0,0 +1,857 @@ +package ie.dcu.swt; + +import ie.dcu.swt.event.*; +import ie.dcu.util.FileUtils; + +import java.io.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.dnd.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +/** + * Miscellaneous SWT Utility functions. + * + * @author Kevin McGuinness + */ +public class SwtUtils { + + /** + * Out-code TOP. + */ + public static final int TOP = java.awt.Rectangle.OUT_TOP; + + /** + * Out-code LEFT. + */ + public static final int LEFT = java.awt.Rectangle.OUT_LEFT; + + /** + * Out-code BOTTOM. + */ + public static final int BOTTOM = java.awt.Rectangle.OUT_BOTTOM; + + /** + * Out-code RIGHT. + */ + public static final int RIGHT = java.awt.Rectangle.OUT_RIGHT; + + /** + * Clone a rectangle. + */ + public static Rectangle clone(Rectangle r) { + return new Rectangle(r.x, r.y, r.width, r.height); + } + + /** + * Clone a point. + */ + public static Point clone(Point p) { + return new Point(p.x, p.y); + } + + + /** + * Scale a rectangle. + * + * @param r + * The rectangle. + * @param scale + * The scale. + * @return A scaled rectangle. + */ + public static Rectangle scale(Rectangle r, float scale) { + return new Rectangle( + (int) Math.floor(r.x * scale), + (int) Math.floor(r.y * scale), + (int) Math.floor(r.width * scale), + (int) Math.floor(r.height * scale) + ); + } + + /** + * Convert a SWT rectangle to an AWT rectangle. + * + * @param r + * An SWT Rectangle. + * @return An AWT Rectangle. + */ + public static java.awt.Rectangle convert(Rectangle r) { + return new java.awt.Rectangle(r.x, r.y, r.width, r.height); + } + + /** + * Determines where the specified coordinates lie with respect to this + * Rectangle. This method computes a binary OR of the + * appropriate mask values indicating, for each side of this + * Rectangle, whether or not the specified coordinates are on + * the same side of the edge as the rest of this Rectangle. + * + * @param r + * A rectangle. + * @param p + * A point. + * @return the logical OR of all appropriate out codes. + * @see #LEFT + * @see #TOP + * @see #RIGHT + * @see #BOTTOM + */ + public static int outcode(Rectangle r, Point p) { + return convert(r).outcode(p.x, p.y); + } + + /** + * Determines where the specified coordinates lie with respect to this + * Rectangle. This method computes a binary OR of the + * appropriate mask values indicating, for each side of this + * Rectangle, whether or not the specified coordinates are on + * the same side of the edge as the rest of this Rectangle. + * + * @param r + * A rectangle. + * @param x + * the specified x coordinate + * @param y + * the specified y coordinate + * @return the logical OR of all appropriate out codes. + * + * @see #LEFT + * @see #TOP + * @see #RIGHT + * @see #BOTTOM + */ + public static int outcode(Rectangle r, float x, float y){ + return convert(r).outcode(x, y); + } + + + // Point class for Liang-Barsky algorithm + private static class Pt { + float x, y; + + Pt(float x, float y) { + this.x = x; this.y = y; + } + } + + + // Rectangle class for Liang-Barsky algorithm + private static class Rect { + float ymin, ymax, xmin, xmax; + + Rect(float x, float y, float w, float h) { + // max needs -1 otherwise its outside the rectangle! + ymin = y; ymax = y + h - 1; + xmin = x; xmax = x + w - 1; + } + + boolean contains(Pt p) { + return p.x >= xmin && p.x <= xmax && p.y >= ymin && p.y <= ymax; + } + } + + + // Liang-Barsky clip test method + private static boolean clipt(float y, float x, Pt p) { + if (y > 0) { + float t = x / y; + if (t > p.y) { + return false; + } else if (t > p.x) { + p.x = t; + } + } else if (y < 0) { + float t = x / y; + if (t < p.x) { + return false; + } else if (t < p.y) { + p.y = t; + } + } else if (x > 0) { + return false; + } + + return true; + } + + + // Liang-barsky line clipping algorithm + private static boolean liangBarskyClip(Rect r, Pt p, Pt q) { + float dx = q.x - p.x; + float dy = q.y - p.y; + + if (dx == 0 && dy == 0 && r.contains(p)) { + return true; + } + + Pt t = new Pt(0, 1); + if (clipt(dx, r.xmin - p.x, t)) { + if (clipt(-dx, p.x - r.xmax, t)) { + if (clipt(dy, r.ymin - p.y, t)) { + if (clipt(-dy, p.y - r.ymax, t)) { + if (t.y < 1) { + q.x = p.x + t.y * dx; + q.y = p.y + t.y * dy; + } + if (t.x > 0) { + p.x += t.x * dx; + p.y += t.x * dy; + } + + return true; + } + } + } + } + + return false; + } + + + /** + * Clip a line using the Liang-Barsky line clipping algorithm. + * + * @param r + * The clipping rectangle. + * @param p + * First point on the line segment. If the point lies outside the + * clipping rectangle it will be clipped to the nearest point on the + * line inside the clipping rectangle on exit. + * @param q + * Second point on the line segment. If the point lies outside the + * clipping rectangle it will be clipped to the nearest point on the + * line inside the clipping rectangle on exit. + * + * @return true if the line has a visible segment inside the + * clipping rectangle, false if it is completely + * outside the clipping window. + */ + public static boolean clip(Rectangle r, Point p, Point q) { + Rect r1 = new Rect(r.x, r.y, r.width, r.height); + Pt p1 = new Pt(p.x, p.y); + Pt p2 = new Pt(q.x, q.y); + boolean result = liangBarskyClip(r1, p1, p2); + p.x = (int) p1.x; + p.y = (int) p1.y; + q.x = (int) p2.x; + q.y = (int) p2.y; + return result; + } + + /** + * Clone the given SWT image. + * + * @param image + * An SWT Image. + * @return A newly created SWT image that is a copy of the given image. + */ + public static Image clone(Image image) { + return new Image(Display.getCurrent(), image, SWT.IMAGE_COPY); + } + + /** + * Apply the given SWT system color as the foreground color in the given + * graphics context. + * + * @param gc + * The graphics context. + * @param swtColor + * An SWT system color. + */ + public static void setForeground(GC gc, int swtColor) { + gc.setForeground(Display.getCurrent().getSystemColor(swtColor)); + } + + /** + * Apply the given SWT system color as the background color in the given + * graphics context. + * + * @param gc + * The graphics context. + * @param swtColor + * An SWT system color. + */ + public static void setBackground(GC gc, int swtColor) { + gc.setBackground(Display.getCurrent().getSystemColor(swtColor)); + } + + /** + * Returns a standard RGB palette. + * + * @return An RGB palette. + */ + public static PaletteData getRgbPalette() { + return new PaletteData(0xff, 0xff00, 0xff0000); + } + + /** + * Create an RGB image with a transparent component, and fill the image with + * the transparent value. + * + * @param width + * The image width. + * @param height + * The image height. + * @return A newly created Image object. + */ + public static Image createTransparentImage(int width, int height) { + PaletteData palette = getRgbPalette(); + + // Use a bit depth of 32 to allow transparent pixel outside RGB space + ImageData data = new ImageData(width, height, 32, palette); + + // Create a transparent pixel outside the RGB color space + int transparent = palette.getPixel(new RGB(255,255,255)) + 2; + data.transparentPixel = transparent; + + // Create a row of transparent pixels + int [] pixels = new int[data.width]; + for (int i = 0; i < pixels.length; i++) { + pixels[i] = transparent; + } + + // Copy pixels to entire image + for (int y = 0; y < data.height; y++) { + data.setPixels(0, y, pixels.length, pixels, 0); + } + + // Create and return the image + return new Image(Display.getCurrent(), data); + } + + /** + * Create a standard image for the current display with the given width and + * height. + * + * @param w + * The image width. + * @param h + * The image height. + * @return A newly created Image object. + */ + public static Image createImage(int w, int h) { + return new Image(Display.getCurrent(), w, h); + } + + /** + * Create a new image with for the current display with the size given by + * the width and height of the specified bounds object. + * + * @param bounds + * The image bounds. + * @return A newly created Image object. + */ + public static Image createImage(Rectangle bounds) { + return createImage(bounds.width, bounds.height); + } + + /** + * Scale the given image to fit inside the specified Rectangle. + * + * @param image + * An image + * @param rect + * The rectangle to fit to + * @param maintainAspectRatio + * if true the aspect ratio of the image is + * maintained. + * @return A newly created scaled image. + */ + public static Image scaleImageToFit(Image image, + Rectangle rect, boolean maintainAspectRatio) + { + return scaleImageToFit(image, rect.width, rect.height, + maintainAspectRatio); + } + + /** + * Scale the given image to fit inside the specified height and width. + * + * @param image + * An image + * @param width + * The width + * @param height + * The height + * @param maintainAspectRatio + * if true the aspect ratio of the image is + * maintained. + * @return A newly created scaled image. + */ + public static Image scaleImageToFit(Image image, + int width, int height, boolean maintainAspectRatio) + { + ImageData data = image.getImageData(); + data = scaleImageDataToFit(data, width, height, maintainAspectRatio); + return new Image(image.getDevice(), data); + } + + /** + * Scale the given ImageData to fit inside the specified Rectangle. + * + * @param data + * A non-null ImageData object + * @param rect + * The rectangle to fit to + * @param maintainAspectRatio + * if true the aspect ratio of the image is + * maintained. + * @return A scaled ImageData object. + */ + public static ImageData scaleImageDataToFit(ImageData data, + Rectangle rect, boolean maintainAspectRatio) + { + return scaleImageDataToFit(data, rect.width, rect.height, + maintainAspectRatio); + } + + /** + * Scale the given ImageData to fit inside the specified height and width. + * + * @param data + * A non-null ImageData object + * @param width + * The width to fit to + * @param height + * The height to fit to + * @param maintainAspectRatio + * if true the aspect ratio of the image is + * maintained. + * @return A scaled ImageData object. + */ + public static ImageData scaleImageDataToFit(ImageData data, + int width, int height, boolean maintainAspectRatio) + { + if (width <= 0) { + throw new IllegalArgumentException("width <= 0"); + } + + if (height <= 0) { + throw new IllegalArgumentException("height <= 0"); + } + + if (data == null) { + throw new IllegalArgumentException("data == null"); + } + + if (!maintainAspectRatio) { + // Direct scale + data = data.scaledTo(width, height); + + } else { + // Compute scale + double sx = width / (double) data.width; + double sy = height / (double) data.height; + double scale = Math.min(sx, sy); + + // Compute new dimensions + int newWidth = (int) (data.width * scale); + int newHeight = (int) (data.height * scale); + + // Clamp dimensions + newWidth = Math.max(Math.min(newWidth, width), 1); + newHeight = Math.max(Math.min(newHeight, height), 1); + + // Scale + data = data.scaledTo(newWidth, newHeight); + } + + return data; + } + + /** + * Load an image for the current display from the given file. + * + * @param file + * A file. + * @return A newly created image. + * @throws IOException + * If an error occurs loading the image. + */ + public static Image loadImage(File file) + throws IOException + { + try { + return new Image(Display.getCurrent(), file.getAbsolutePath()); + } catch (SWTException e) { + // Translate to checked exception! + throw new IOException("SWTException: " + e.getMessage()); + } + } + + /** + * Load an image for the current display from the given InputStream. + * + * @param in + * An input stream. + * @return A newly created image. + * @throws IOException + * If an error occurs loading the image. + */ + public static Image loadImage(InputStream in) + throws IOException + { + try { + return new Image(Display.getCurrent(), in); + } catch (SWTException e) { + // Translate to checked exception! + throw new IOException("SWTException: " + e.getMessage()); + } + } + + /** + * Load the ImageData object from the given file. + * + * @param file + * A file. + * @return A newly created image. + * @throws IOException + * If an error occurs loading the image. + */ + public static ImageData loadImageData(File file) + throws IOException + { + try { + return new ImageData(file.getAbsolutePath()); + } catch (SWTException e) { + // Translate to checked exception! + throw new IOException("SWTException: " + e.getMessage()); + } + } + + /** + * Load the ImageData object from the given InputStream. + * + * @param in + * An input stream. + * @return A newly created image. + * @throws IOException + * If an error occurs loading the image. + */ + public static ImageData loadImageData(InputStream in) + throws IOException + { + try { + return new ImageData(in); + } catch (SWTException e) { + // Translate to checked exception! + throw new IOException("SWTException: " + e.getMessage()); + } + } + + /** + * Add a label to the given ToolBar. The label will be aligned to the + * vertical center of the ToolBar. + * + * @param bar + * A ToolBar. + * @param text + * The label text. + */ + public static void addLabel(ToolBar bar, String text) { + Composite box = new Composite(bar, SWT.NONE); + box.setLayout(new GridLayout()); + + // Create label + Label label = new Label(box, SWT.NONE); + label.setText(text); + + // Layout in center of toolbar + GridData data = new GridData(); + data.grabExcessVerticalSpace = true; + data.verticalAlignment = SWT.CENTER; + label.setLayoutData(data); + + // Set item size + Point sz = box.computeSize(SWT.DEFAULT, SWT.DEFAULT); + ToolItem item = new ToolItem(bar, SWT.SEPARATOR); + item.setWidth(sz.x); + + // Set control + item.setControl(box); + } + + /** + * Add a separator to the given ToolBar. + * + * @param bar + * A ToolBar. + */ + public static void addSeparator(ToolBar bar) { + new ToolItem(bar, SWT.SEPARATOR); + } + + /** + * Add a Combo box to the given ToolBar. + * + * @param bar + * A ToolBar. + * @param width + * The horizontal width to make the ToolBar. + * @param style + * The Combo box style. + */ + public static Combo addCombo(ToolBar bar, int width, int style) { + ToolItem item = new ToolItem(bar, SWT.SEPARATOR); + Combo combo = new Combo(bar, style); + item.setWidth(width); + item.setControl(combo); + return combo; + } + + /** + * Center the given shell on the Display. + * + * @param shell + * A shell. + */ + public static void center(Shell shell) { + Point p = shell.getSize(); + Rectangle area = shell.getDisplay().getClientArea(); + + int x = area.width / 2 - p.x / 2 + area.x; + int y = area.height / 2 - p.y / 2 + area.y; + + shell.setLocation(x, y); + } + + /** + * Center the given shell with respect to the given parent shell. + * + * @param parent + * A shell. + * @param shell + * The shell to center. + */ + public static void center(Shell parent, Shell shell) { + Point p = shell.getSize(); + Rectangle area = parent.getBounds(); + + int x = area.width / 2 - p.x / 2 + area.x; + int y = area.height / 2 - p.y / 2 + area.y; + + shell.setLocation(x, y); + } + + /** + * Returns the SWT image format constant for the given by examining + * the file extension of the file. + * + * @param file + * A file. + * @return The SWT image format constant. + */ + public static int getImageFormat(File file) { + String ext = FileUtils.getExtension(file); + + if (ext != null) { + if (ext.equals("bmp")) { + return SWT.IMAGE_BMP; + } else if (ext.equals("jpg") || ext.equals("jpeg")) { + return SWT.IMAGE_JPEG; + } else if (ext.equals("png")) { + return SWT.IMAGE_PNG; + } else if (ext.equals("gif")) { + return SWT.IMAGE_GIF; + } else if (ext.equals("ico")) { + return SWT.IMAGE_ICO; + } + } + + return -1; + } + + /** + * Save the given SWT image to the given file. The format will be determined + * from the file extension. + * + * @param im + * An image object. + * @param file + * The destination file. + * @throws IOException + * If there is an error saving the file or the format cannot be + * determined from the filename. + */ + public static void saveImage(Image im, File file) + throws IOException { + + saveImage(im.getImageData(), file); + } + + /** + * Save the given SWT ImageData to the given file. The format will be + * determined from the file extension. + * + * @param im + * An ImageData object. + * @param file + * The destination file. + * @throws IOException + * If there is an error saving the file or the format cannot be + * determined from the filename. + */ + public static void saveImage(ImageData im, File file) + throws IOException { + + // Check if file is a directory + if (file.isDirectory()) { + throw new FileNotFoundException(String.format("%s is a directory", file)); + } + + // Check if we can write to file + if (file.exists()) { + if (!file.canWrite()) { + throw new IOException(String.format("Cannot write to %s", file)); + } + } + + // Get image format + int format = getImageFormat(file); + + // Check for unrecognized format + if (format < 0) { + String ext = FileUtils.getExtension(file); + throw new IOException(String.format("Unknown format \"%s\"", ext)); + } + + // Create image loader + ImageLoader loader = new ImageLoader(); + loader.data = new ImageData[] { im }; + + try { + // Save image + loader.save(file.getAbsolutePath(), format); + + } catch (SWTException e) { + // Change unchecked exception to checked one + throw new IOException("SWT Exception: " + e.getMessage()); + } + + // Done + return; + } + + /** + * Save the given SWT image to the given OutputStream. + * + * @param im + * An image object. + * @param out + * The destination output stream. + * @param format + * The SWT format constant. + * @throws IOException + * If there is an error saving the to the output stream. + */ + public static void saveImage(Image im, OutputStream out, int format) + throws IOException + { + saveImage(im.getImageData(), out, format); + } + + /** + * Save the given SWT ImageData object to the given OutputStream. + * + * @param im + * An ImageData object. + * @param out + * The destination output stream. + * @param format + * The SWT format constant. + * @throws IOException + * If there is an error saving the to the output stream. + */ + public static void saveImage(ImageData im, OutputStream out, int format) + throws IOException + { + ImageLoader loader = new ImageLoader(); + loader.data = new ImageData[] { im }; + + try { + // Save image + loader.save(out, format); + + } catch (SWTException e) { + // Change unchecked exception to checked one + throw new IOException("SWT Exception: " + e.getMessage()); + } + } + + /** + * Create a horizontal separator for the given parent. + * + * @param parent + * A composite. + * @return The created separator control. + */ + public static Control createSeparator(Composite parent) { + return new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); + } + + /** + * Turn a SWT control into a file drop target. + * + * @param control + * An SWT control (not null). + * @param listener + * A file drop listener (not null). + */ + public static void createFileDropTarget( + final Control control, + final FileDropListener listener) + { + // Create target + DropTarget target = new DropTarget( + control, DND.DROP_DEFAULT | DND.DROP_MOVE + ); + + // Create transfer + final FileTransfer transfer = FileTransfer.getInstance(); + target.setTransfer(new Transfer[] { transfer }); + + // Add listener + target.addDropListener(new DropTargetAdapter() { + public void drop(final DropTargetEvent event) { + + + if (transfer.isSupportedType(event.currentDataType)) { + String[] files = (String[]) event.data; + + // Send event + listener.drop(new FileDropEvent(control, files)); + } + } + }); + + return; + } + + + /** + * Compress and RGB object into a ARGB integer. + * + * @param rgb + * RGB object. + * @return An ARGB integer. + */ + public static int rgb2int(RGB rgb) { + return (rgb.red & 0xff) << 16 | + (rgb.green & 0xff) << 8 | + (rgb.blue & 0xff); + } + + /** + * De-compress an ARGB integer into an RGB object. + * + * @param v + * an ARGB integer. + * @return An RGB object. + */ + public static RGB int2rgb(int v) { + return new RGB((v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff); + } +} diff --git a/Annotation/src/ie/dcu/swt/event/FileDropEvent.class b/Annotation/src/ie/dcu/swt/event/FileDropEvent.class new file mode 100644 index 0000000..cd5d9cf Binary files /dev/null and b/Annotation/src/ie/dcu/swt/event/FileDropEvent.class differ diff --git a/Annotation/src/ie/dcu/swt/event/FileDropEvent.java b/Annotation/src/ie/dcu/swt/event/FileDropEvent.java new file mode 100644 index 0000000..f8e81b0 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/event/FileDropEvent.java @@ -0,0 +1,46 @@ +package ie.dcu.swt.event; + +import java.io.*; +import java.util.*; + +/** + * A file drop event. + * + * @author Kevin McGuinness + */ +public class FileDropEvent extends EventObject { + + /** + * Serialization UID. + */ + private static final long serialVersionUID = -7379037769871853671L; + + /** + * The files. + */ + private final ArrayList files; + + /** + * Create a file drop event. + * + * @param source + * The source of the file drop. + * @param files + * A list of absolute file paths. + */ + public FileDropEvent(Object source, String[] files) { + super(source); + this.files = new ArrayList(files.length); + for (String file : files) { + this.files.add(new File(file)); + } + } + + /** + * Returns an immutable collection of the files for the drop. + */ + public Collection files() { + return Collections.unmodifiableCollection(files); + } + +} diff --git a/Annotation/src/ie/dcu/swt/event/FileDropListener.class b/Annotation/src/ie/dcu/swt/event/FileDropListener.class new file mode 100644 index 0000000..60330e5 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/event/FileDropListener.class differ diff --git a/Annotation/src/ie/dcu/swt/event/FileDropListener.java b/Annotation/src/ie/dcu/swt/event/FileDropListener.java new file mode 100644 index 0000000..7d8be6b --- /dev/null +++ b/Annotation/src/ie/dcu/swt/event/FileDropListener.java @@ -0,0 +1,19 @@ +package ie.dcu.swt.event; + +import java.util.*; + +/** + * A listener for FileDropEvents. + * + * @author Kevin McGuinness + */ +public interface FileDropListener extends EventListener { + + /** + * Called when a drop occurs. + * + * @param evt + * The FileDropEvent object. + */ + public void drop(FileDropEvent evt); +} diff --git a/Annotation/src/ie/dcu/swt/event/ImageEvent.class b/Annotation/src/ie/dcu/swt/event/ImageEvent.class new file mode 100644 index 0000000..3e14d9f Binary files /dev/null and b/Annotation/src/ie/dcu/swt/event/ImageEvent.class differ diff --git a/Annotation/src/ie/dcu/swt/event/ImageEvent.java b/Annotation/src/ie/dcu/swt/event/ImageEvent.java new file mode 100644 index 0000000..e223ad6 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/event/ImageEvent.java @@ -0,0 +1,56 @@ +package ie.dcu.swt.event; + +import ie.dcu.swt.ObservableImage; + +import java.util.EventObject; + +import org.eclipse.swt.graphics.Rectangle; + +/** + * An image event. + * + * @see ObservableImage + * @see ImageListener + * @author Kevin McGuinness + * + */ +public class ImageEvent extends EventObject { + private static final long serialVersionUID = 1L; + + /** + * The image the fired the event. + */ + public final ObservableImage image; + + /** + * The rectangle that was modified. + */ + public final Rectangle modified; + + /** + * Flag to indicate that the image dimensions changed. + */ + private final boolean dimensionsChanged; + + public ImageEvent( + ObservableImage image, + Rectangle modified, + boolean dimensionsChanged + ) { + + super(image); + this.image = image; + this.dimensionsChanged = dimensionsChanged; + + if (modified == null) { + modified = image.getBounds(); + } + + this.modified = modified; + } + + public boolean dimensionsChanged() { + return dimensionsChanged; + } + +} diff --git a/Annotation/src/ie/dcu/swt/event/ImageListener.class b/Annotation/src/ie/dcu/swt/event/ImageListener.class new file mode 100644 index 0000000..5b17188 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/event/ImageListener.class differ diff --git a/Annotation/src/ie/dcu/swt/event/ImageListener.java b/Annotation/src/ie/dcu/swt/event/ImageListener.java new file mode 100644 index 0000000..b3522a6 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/event/ImageListener.java @@ -0,0 +1,20 @@ +package ie.dcu.swt.event; + +import java.util.*; + +/** + * Interface for image listeners. + * + * @see ie.dcu.swt.ObservableImage + * @author Kevin McGuinness + */ +public interface ImageListener extends EventListener { + + /** + * Called when the image is changed. + * + * @param e + * The image event object. + */ + public void imageChanged(ImageEvent e); +} diff --git a/Annotation/src/ie/dcu/swt/event/ZoomEvent.class b/Annotation/src/ie/dcu/swt/event/ZoomEvent.class new file mode 100644 index 0000000..cd9d99d Binary files /dev/null and b/Annotation/src/ie/dcu/swt/event/ZoomEvent.class differ diff --git a/Annotation/src/ie/dcu/swt/event/ZoomEvent.java b/Annotation/src/ie/dcu/swt/event/ZoomEvent.java new file mode 100644 index 0000000..f94d8a8 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/event/ZoomEvent.java @@ -0,0 +1,18 @@ +package ie.dcu.swt.event; + +import ie.dcu.swt.ImageControl; + +import java.util.EventObject; + +public class ZoomEvent extends EventObject { + private static final long serialVersionUID = 1L; + + public final ImageControl view; + public final float scale; + + public ZoomEvent(ImageControl view) { + super(view); + this.view = view; + this.scale = view.getZoom(); + } +} diff --git a/Annotation/src/ie/dcu/swt/event/ZoomListener.class b/Annotation/src/ie/dcu/swt/event/ZoomListener.class new file mode 100644 index 0000000..7df5f99 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/event/ZoomListener.class differ diff --git a/Annotation/src/ie/dcu/swt/event/ZoomListener.java b/Annotation/src/ie/dcu/swt/event/ZoomListener.java new file mode 100644 index 0000000..ac2c726 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/event/ZoomListener.java @@ -0,0 +1,7 @@ +package ie.dcu.swt.event; + +import java.util.*; + +public interface ZoomListener extends EventListener { + public void zoomChanged(ZoomEvent e); +} diff --git a/Annotation/src/ie/dcu/swt/layout/BorderData.class b/Annotation/src/ie/dcu/swt/layout/BorderData.class new file mode 100644 index 0000000..81bb88a Binary files /dev/null and b/Annotation/src/ie/dcu/swt/layout/BorderData.class differ diff --git a/Annotation/src/ie/dcu/swt/layout/BorderData.java b/Annotation/src/ie/dcu/swt/layout/BorderData.java new file mode 100644 index 0000000..8c61253 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/layout/BorderData.java @@ -0,0 +1,11 @@ +package ie.dcu.swt.layout; + +public enum BorderData { + North, South, Center, East, West, Ignore; + + public final int index; + + private BorderData() { + index = ordinal(); + } +}; diff --git a/Annotation/src/ie/dcu/swt/layout/BorderLayout.class b/Annotation/src/ie/dcu/swt/layout/BorderLayout.class new file mode 100644 index 0000000..2a5c927 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/layout/BorderLayout.class differ diff --git a/Annotation/src/ie/dcu/swt/layout/BorderLayout.java b/Annotation/src/ie/dcu/swt/layout/BorderLayout.java new file mode 100644 index 0000000..d255f82 --- /dev/null +++ b/Annotation/src/ie/dcu/swt/layout/BorderLayout.java @@ -0,0 +1,187 @@ +package ie.dcu.swt.layout; + +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.widgets.*; + +/** + * Port of the AWT BorderLayout. + * + * @author Kevin McGuinness + */ +public class BorderLayout extends Layout { + + // Typedef indices + private static final int N = BorderData.North.index; + private static final int S = BorderData.South.index; + private static final int C = BorderData.Center.index; + private static final int E = BorderData.East.index; + private static final int W = BorderData.West.index; + + // Controls in all the regions. + private Control[] controls = new Control[5]; + + // Cached sizes. + private Point[] sizes; + + // Preferred width and height + int width, height; + + // Spacing between components + int hgap, vgap; + + public BorderLayout() { + this(0); + } + + public BorderLayout(int space) { + hgap = vgap = space; + } + + public BorderLayout(int hgap, int vgap) { + this.hgap = hgap; + this.vgap = vgap; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite + * , int, int, boolean) + */ + protected Point computeSize(Composite composite, int wHint, int hHint, + boolean flushCache) { + + if (sizes == null || flushCache == true) { + refreshSizes(composite.getChildren()); + } + + int w = wHint; + int h = hHint; + + if (w == SWT.DEFAULT) + w = width; + if (h == SWT.DEFAULT) + h = height; + + return new Point(w, h); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, + * boolean) + */ + protected void layout(Composite composite, boolean flushCache) { + + if (flushCache || sizes == null) { + refreshSizes(composite.getChildren()); + } + + Rectangle r = composite.getClientArea(); + + int tg = 0; + int bg = 0; + int lg = 0; + int rg = 0; + + if (controls[N] != null) { + int x = r.x; + int y = r.y; + int w = r.width; + int h = sizes[N].y; + + controls[N].setBounds(x, y, w, h); + + tg += hgap; + } + + if (controls[S] != null) { + int x = r.x; + int y = r.y + r.height - sizes[S].y; + int w = r.width; + int h = sizes[S].y; + + controls[S].setBounds(x, y, w, h); + + bg += hgap; + } + + if (controls[W] != null) { + int x = r.x; + int y = r.y + sizes[N].y + tg; + int w = sizes[W].x; + int h = r.height - sizes[N].y - sizes[S].y - (tg + bg); + + controls[W].setBounds(x, y, w, h); + + lg += vgap; + } + + if (controls[E] != null) { + int x = r.x + r.width - sizes[E].x; + int y = r.y + sizes[N].y + tg; + int w = sizes[E].x; + int h = r.height - sizes[N].y - sizes[S].y - (tg + bg); + + controls[E].setBounds(x, y, w, h); + + rg += vgap; + } + + if (controls[C] != null) { + int x = r.x + sizes[W].x + lg; + int y = r.y + sizes[N].y + tg; + int w = r.width - sizes[W].x - sizes[E].x - (lg + rg); + int h = r.height - sizes[N].y - sizes[S].y - (tg + bg); + + controls[C].setBounds(x, y, w, h); + } + + return; + } + + private void refreshSizes(Control[] children) { + for (Control c : children) { + Object o = c.getLayoutData(); + + if (o instanceof BorderData) { + BorderData data = (BorderData) o; + if (data != BorderData.Ignore) { + controls[data.index] = c; + } + } else { + // Default + controls[C] = c; + } + } + + width = height = 0; + + if (sizes == null) { + sizes = new Point[5]; + } + + for (int i = 0; i < controls.length; i++) { + Control control = controls[i]; + + if (control == null) { + sizes[i] = new Point(0, 0); + } else { + sizes[i] = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); + } + } + + width = Math.max(width, sizes[N].x); + width = Math.max(width, sizes[W].x + sizes[C].x + sizes[E].x); + width = Math.max(width, sizes[S].x); + + height = Math.max(Math.max(sizes[W].y, sizes[E].y), sizes[C].y) + + sizes[N].y + sizes[S].y; + + return; + } +} \ No newline at end of file diff --git a/Annotation/src/ie/dcu/swt/layout/LayoutFactory.class b/Annotation/src/ie/dcu/swt/layout/LayoutFactory.class new file mode 100644 index 0000000..55766d3 Binary files /dev/null and b/Annotation/src/ie/dcu/swt/layout/LayoutFactory.class differ diff --git a/Annotation/src/ie/dcu/swt/layout/LayoutFactory.java b/Annotation/src/ie/dcu/swt/layout/LayoutFactory.java new file mode 100644 index 0000000..3e356ef --- /dev/null +++ b/Annotation/src/ie/dcu/swt/layout/LayoutFactory.java @@ -0,0 +1,36 @@ +package ie.dcu.swt.layout; + +import org.eclipse.swt.*; +import org.eclipse.swt.layout.*; + +/** + * Factory for layouts and layout data objects. + * + * @author Kevin McGuinness + */ +public class LayoutFactory { + + public static GridLayout createGridLayout( + int margin, int spacing, int ncols, boolean equal + ) { + GridLayout layout = createGridLayout(margin, spacing); + layout.numColumns = ncols; + layout.makeColumnsEqualWidth = equal; + return layout; + } + + + public static GridLayout createGridLayout(int margin, int spacing) { + GridLayout layout = new GridLayout(); + layout.marginWidth = margin; + layout.marginHeight = margin; + layout.horizontalSpacing = spacing; + layout.verticalSpacing = spacing; + return layout; + } + + + public static GridData createGridData() { + return new GridData(SWT.FILL, SWT.FILL, true, true); + } +} diff --git a/Annotation/src/ie/dcu/util/ArrayUtils.class b/Annotation/src/ie/dcu/util/ArrayUtils.class new file mode 100644 index 0000000..ccf3d9b Binary files /dev/null and b/Annotation/src/ie/dcu/util/ArrayUtils.class differ diff --git a/Annotation/src/ie/dcu/util/ArrayUtils.java b/Annotation/src/ie/dcu/util/ArrayUtils.java new file mode 100644 index 0000000..d8b24a6 --- /dev/null +++ b/Annotation/src/ie/dcu/util/ArrayUtils.java @@ -0,0 +1,543 @@ +package ie.dcu.util; + +import java.util.*; + +/** + * Utilities for arrays. + * + * @author Kevin McGuinness + */ +public class ArrayUtils { + + /** + * Remove the given indices from the given collection. + * + * @param c + * The collection. + * @param indices + * A list of indices (will be sorted). + */ + public static void remove(Collection c, int[] indices) { + Arrays.sort(indices); + + Iterator iterator = c.iterator(); + for (int i = 0; iterator.hasNext(); i++) { + iterator.next(); + + if (Arrays.binarySearch(indices, i) >= 0) { + iterator.remove(); + } + } + + return; + } + + + public static void arrayCopy(Object src, int srcPos, Object dst, + int dstPos, int length) + { + if (dst.getClass().equals(src.getClass())) { + + System.arraycopy(src, srcPos, dst, dstPos, length); + + } else { + + // Try for arrays of different primitive types + + if (src instanceof byte[] && dst instanceof short[]) { + + // Copy from an array of bytes to array of shorts + arrayCopy((byte[]) src, srcPos, (short[]) dst, dstPos, length); + + } else if (src instanceof byte[] && dst instanceof int[]) { + + // Copy from an array of bytes to array of ints + arrayCopy((byte[]) src, srcPos, (int[]) dst, dstPos, length); + + } else if (src instanceof byte[] && dst instanceof long[]) { + + // Copy from an array of bytes to array of longs + arrayCopy((byte[]) src, srcPos, (long[]) dst, dstPos, length); + + } else if (src instanceof byte[] && dst instanceof float[]) { + + // Copy from an array of bytes to array of floats + arrayCopy((byte[]) src, srcPos, (float[]) dst, dstPos, length); + + } else if (src instanceof byte[] && dst instanceof double[]) { + + // Copy from an array of bytes to array of doubles + arrayCopy((byte[]) src, srcPos, (double[]) dst, dstPos, length); + + } else if (src instanceof short[] && dst instanceof byte[]) { + + // Copy from an array of shorts to array of bytes + arrayCopy((short[]) src, srcPos, (byte[]) dst, dstPos, length); + + } else if (src instanceof short[] && dst instanceof int[]) { + + // Copy from an array of shorts to array of ints + arrayCopy((short[]) src, srcPos, (int[]) dst, dstPos, length); + + } else if (src instanceof short[] && dst instanceof long[]) { + + // Copy from an array of shorts to array of longs + arrayCopy((short[]) src, srcPos, (long[]) dst, dstPos, length); + + } else if (src instanceof short[] && dst instanceof float[]) { + + // Copy from an array of shorts to array of floats + arrayCopy((short[]) src, srcPos, (float[]) dst, dstPos, length); + + } else if (src instanceof short[] && dst instanceof double[]) { + + // Copy from an array of shorts to array of doubles + arrayCopy((short[]) src, srcPos, (double[]) dst, dstPos, length); + + } else if (src instanceof int[] && dst instanceof byte[]) { + + // Copy from an array of ints to array of bytes + arrayCopy((int[]) src, srcPos, (byte[]) dst, dstPos, length); + + } else if (src instanceof int[] && dst instanceof short[]) { + + // Copy from an array of ints to array of shorts + arrayCopy((int[]) src, srcPos, (short[]) dst, dstPos, length); + + } else if (src instanceof int[] && dst instanceof long[]) { + + // Copy from an array of ints to array of longs + arrayCopy((int[]) src, srcPos, (long[]) dst, dstPos, length); + + } else if (src instanceof int[] && dst instanceof float[]) { + + // Copy from an array of ints to array of floats + arrayCopy((int[]) src, srcPos, (float[]) dst, dstPos, length); + + } else if (src instanceof int[] && dst instanceof double[]) { + + // Copy from an array of ints to array of doubles + arrayCopy((int[]) src, srcPos, (double[]) dst, dstPos, length); + + } else if (src instanceof long[] && dst instanceof byte[]) { + + // Copy from an array of longs to array of bytes + arrayCopy((long[]) src, srcPos, (byte[]) dst, dstPos, length); + + } else if (src instanceof long[] && dst instanceof short[]) { + + // Copy from an array of longs to array of shorts + arrayCopy((long[]) src, srcPos, (short[]) dst, dstPos, length); + + } else if (src instanceof long[] && dst instanceof int[]) { + + // Copy from an array of longs to array of ints + arrayCopy((long[]) src, srcPos, (int[]) dst, dstPos, length); + + } else if (src instanceof long[] && dst instanceof float[]) { + + // Copy from an array of longs to array of floats + arrayCopy((long[]) src, srcPos, (float[]) dst, dstPos, length); + + } else if (src instanceof long[] && dst instanceof double[]) { + + // Copy from an array of longs to array of doubles + arrayCopy((long[]) src, srcPos, (double[]) dst, dstPos, length); + + } else if (src instanceof float[] && dst instanceof byte[]) { + + // Copy from an array of floats to array of bytes + arrayCopy((float[]) src, srcPos, (byte[]) dst, dstPos, length); + + } else if (src instanceof float[] && dst instanceof short[]) { + + // Copy from an array of floats to array of shorts + arrayCopy((float[]) src, srcPos, (short[]) dst, dstPos, length); + + } else if (src instanceof float[] && dst instanceof int[]) { + + // Copy from an array of floats to array of ints + arrayCopy((float[]) src, srcPos, (int[]) dst, dstPos, length); + + } else if (src instanceof float[] && dst instanceof long[]) { + + // Copy from an array of floats to array of longs + arrayCopy((float[]) src, srcPos, (long[]) dst, dstPos, length); + + } else if (src instanceof float[] && dst instanceof double[]) { + + // Copy from an array of floats to array of doubles + arrayCopy((float[]) src, srcPos, (double[]) dst, dstPos, length); + + } else if (src instanceof double[] && dst instanceof byte[]) { + + // Copy from an array of doubles to array of bytes + arrayCopy((double[]) src, srcPos, (byte[]) dst, dstPos, length); + + } else if (src instanceof double[] && dst instanceof short[]) { + + // Copy from an array of doubles to array of shorts + arrayCopy((double[]) src, srcPos, (short[]) dst, dstPos, length); + + } else if (src instanceof double[] && dst instanceof int[]) { + + // Copy from an array of doubles to array of ints + arrayCopy((double[]) src, srcPos, (int[]) dst, dstPos, length); + + } else if (src instanceof double[] && dst instanceof long[]) { + + // Copy from an array of doubles to array of longs + arrayCopy((double[]) src, srcPos, (long[]) dst, dstPos, length); + + } else if (src instanceof double[] && dst instanceof float[]) { + + // Copy from an array of doubles to array of floats + arrayCopy((double[]) src, srcPos, (float[]) dst, dstPos, length); + + } else { + + throw new ArrayStoreException(); + } + } + } + + + public static void arrayCopy(byte[] src, int srcPos, + short[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (short) src[srcPos++]; + } + } + + public static void arrayCopy(byte[] src, int srcPos, + int[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (int) src[srcPos++]; + } + } + + public static void arrayCopy(byte[] src, int srcPos, + long[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (long) src[srcPos++]; + } + } + + public static void arrayCopy(byte[] src, int srcPos, + float[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (float) src[srcPos++]; + } + } + + public static void arrayCopy(byte[] src, int srcPos, + double[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (double) src[srcPos++]; + } + } + + public static void arrayCopy(short[] src, int srcPos, + byte[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (byte) src[srcPos++]; + } + } + + public static void arrayCopy(short[] src, int srcPos, + int[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (int) src[srcPos++]; + } + } + + public static void arrayCopy(short[] src, int srcPos, + long[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (long) src[srcPos++]; + } + } + + public static void arrayCopy(short[] src, int srcPos, + float[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (float) src[srcPos++]; + } + } + + public static void arrayCopy(short[] src, int srcPos, + double[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (double) src[srcPos++]; + } + } + + public static void arrayCopy(int[] src, int srcPos, + byte[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (byte) src[srcPos++]; + } + } + + public static void arrayCopy(int[] src, int srcPos, + short[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (short) src[srcPos++]; + } + } + + public static void arrayCopy(int[] src, int srcPos, + long[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (long) src[srcPos++]; + } + } + + public static void arrayCopy(int[] src, int srcPos, + float[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (float) src[srcPos++]; + } + } + + public static void arrayCopy(int[] src, int srcPos, + double[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (double) src[srcPos++]; + } + } + + public static void arrayCopy(long[] src, int srcPos, + byte[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (byte) src[srcPos++]; + } + } + + public static void arrayCopy(long[] src, int srcPos, + short[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (short) src[srcPos++]; + } + } + + public static void arrayCopy(long[] src, int srcPos, + int[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (int) src[srcPos++]; + } + } + + public static void arrayCopy(long[] src, int srcPos, + float[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (float) src[srcPos++]; + } + } + + public static void arrayCopy(long[] src, int srcPos, + double[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (double) src[srcPos++]; + } + } + + public static void arrayCopy(float[] src, int srcPos, + byte[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (byte) src[srcPos++]; + } + } + + public static void arrayCopy(float[] src, int srcPos, + short[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (short) src[srcPos++]; + } + } + + public static void arrayCopy(float[] src, int srcPos, + int[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (int) src[srcPos++]; + } + } + + public static void arrayCopy(float[] src, int srcPos, + long[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (long) src[srcPos++]; + } + } + + public static void arrayCopy(float[] src, int srcPos, + double[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (double) src[srcPos++]; + } + } + + public static void arrayCopy(double[] src, int srcPos, + byte[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (byte) src[srcPos++]; + } + } + + public static void arrayCopy(double[] src, int srcPos, + short[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (short) src[srcPos++]; + } + } + + public static void arrayCopy(double[] src, int srcPos, + int[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (int) src[srcPos++]; + } + } + + public static void arrayCopy(double[] src, int srcPos, + long[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (long) src[srcPos++]; + } + } + + public static void arrayCopy(double[] src, int srcPos, + float[] dst, int dstPos, int length) + { + checkCopy(src.length, srcPos, dst.length, dstPos, length); + + for (int i = 0; i < length; i++) { + dst[dstPos++] = (float) src[srcPos++]; + } + } + + private static void checkCopy(int srcLen, int srcPos, + int dstLen, int dstPos, int length) + { + if (srcPos < 0) { + throw new IllegalArgumentException("srcPos < 0"); + } + + if (dstPos < 0) { + throw new IllegalArgumentException("dstPos < 0"); + } + + if (length < 0) { + throw new IllegalArgumentException("length < 0"); + } + + if (srcPos + length > srcLen) { + throw new IllegalArgumentException("srcPos + length > src.length"); + } + + if (dstPos + length > dstLen) { + throw new IllegalArgumentException("dstPos + length > dst.length"); + } + } + + public static void main(String[] args) { + int[] srcArray = { + 1, 2, 3, 4, 5 + }; + + short[] dstArray = new short[srcArray.length]; + + arrayCopy(srcArray, 0, dstArray, 0, srcArray.length); + + Object srcObj = srcArray; + Object dstObj = dstArray; + + arrayCopy(srcObj, 0, dstObj, 0, srcArray.length); + } +} diff --git a/Annotation/src/ie/dcu/util/FileUtils.class b/Annotation/src/ie/dcu/util/FileUtils.class new file mode 100644 index 0000000..b547efb Binary files /dev/null and b/Annotation/src/ie/dcu/util/FileUtils.class differ diff --git a/Annotation/src/ie/dcu/util/FileUtils.java b/Annotation/src/ie/dcu/util/FileUtils.java new file mode 100644 index 0000000..0c6e6ac --- /dev/null +++ b/Annotation/src/ie/dcu/util/FileUtils.java @@ -0,0 +1,383 @@ +package ie.dcu.util; + +import java.io.*; +import java.net.*; + +/** + * Utility functions for file and filename manipulation. + * + * @author Kevin McGuinness + */ +public class FileUtils { + + /** + * Size of the copy file buffer. + */ + private static final int BUFFER_SIZE = 8092; + + + /** + * Returns the file extension of the file. This method returns {@code null} if + * the file has no extension. The method also returns {@code null}: + * + *
    + *
  • If the filename contains a period as it's last character
  • + *
  • If the filename contains a single period as its first character
  • + *
+ * + * The returned extension is always lowercase. + * + * @param file + * The file. + * @param includePeriod + * Set to {@code true} to include the period in the returned + * extension. + * @return The file extension, or {@code null} + */ + public static final String getExtension(File file, boolean includePeriod) { + String filename = file.getName(); + int idx = filename.lastIndexOf('.'); + + // If the period is not the first character or the last + if (idx > 0 && idx < filename.length() - 1) { + + if (!includePeriod) { + idx++; + } + + return filename.substring(idx).toLowerCase(); + } + + return null; + } + + + /** + * Returns the file extension of the file. This method returns {@code null} if + * the file has no extension. The method also returns {@code null}: + * + *
    + *
  • If the filename contains a period as it's last character
  • + *
  • If the filename contains a single period as its first character
  • + *
+ * + * This method does not include the period in the file extension. The returned + * extension is always lower-case. + * + * @param file + * The file. + * @return The file extension, or {@code null} + */ + public static final String getExtension(File file) { + return getExtension(file, false); + } + + + /** + * Remove the file extension from the filename, if it has one. + * + * @param filename + * The filename. + * @return The filename with the extension removed. + */ + public static final String removeExtension(String filename) { + int idx = filename.lastIndexOf('.'); + if (idx > 0 && idx < filename.length() - 1) { + return filename.substring(0, idx); + } + return filename; + } + + + /** + * Replace the file extension with another. If the file has no existing + * extension, the new extension will be appended. If the new extension is not + * prefixed with a period, one will be added. + * + * @param filename + * The filename (not a file path). + * @param extension + * The new extension. + * @return The filename with the extension replaced. + */ + public static final String replaceExtension(String filename, String extension) { + boolean period = extension.startsWith("."); + + int idx = filename.lastIndexOf('.'); + + if (idx > 0 && idx < filename.length() - 1) { + // Strip and append new extension + if (period) { + return filename.substring(0, idx) + extension; + } else { + return filename.substring(0, idx) + "." + extension; + } + } + + if (period) { + return filename + extension; + } + + return filename + "." + extension; + } + + + /** + * Returns true if the filename has an extension. + * + * @param filename + * The file name (not a file path). + * @return {@code true} if it has an extension. + */ + public static boolean hasExtension(String filename) { + int idx = filename.lastIndexOf('.'); + return (idx > 0 && idx < filename.length() - 1); + } + + + /** + * Returns true if the filename has an extension. + * + * @param file + * The file. + * @return {@code true} if it has an extension. + */ + public static boolean hasExtension(File file) { + return hasExtension(file.getName()); + } + + + /** + * Close the stream. Does nothing if it is already closed and ignores any I/O + * exception that is thrown. + * + * @param c + * The stream, or {@code null} + */ + public static void close(Closeable c) { + if (c == null) { + return; + } + + try { + c.close(); + } catch (IOException e) { + // Intentionally empty + } + } + + + /** + * Copy a source file to a destination. If the destination file exists it is + * overwritten. If the destination file is a directory, the file is copied to + * that directory. + * + * @param src + * The source file. + * @param dst + * The target file. + * @throws IOException + * If there is a problem copying the file. + */ + public static void copy(File src, File dst) throws IOException { + + // If directory, copy to file of the same name in that directory + if (dst.isDirectory()) { + dst = new File(dst, src.getName()); + } + + InputStream in = null; + OutputStream out = null; + + try { + in = new FileInputStream(src); + out = new FileOutputStream(dst); + + // Copy streams + copy(in, out); + + } finally { + // Close streams + + if (in != null) { + in.close(); + } + + if (out != null) { + out.close(); + } + } + + return; + } + + + /** + * Copy the data from the input stream to the output stream. The streams are + * not closed after the copy. + * + * @param in + * The input stream. + * @param out + * The output stream. + * @throws IOException + * If there is a problem performing the copy. + */ + public static void copy(InputStream in, OutputStream out) throws IOException { + byte[] buff = new byte[BUFFER_SIZE]; + + int len; + while ((len = in.read(buff)) > 0) { + out.write(buff, 0, len); + } + } + + + /** + * Move the src file to dst. Semantics are the same as copy except that + * the source file is deleted after the operation. + * + * @param src + * The source file. + * @param dst + * The destination. + * @return {@code true} if the move is sucessful, {@code false} if the source + * file cannot be removed. + * @throws IOException + */ + public static boolean move(File src, File dst) throws IOException { + copy(src, dst); + return src.delete(); + } + + + /** + * Throws an {@link FileNotFoundException} if the file does not exist. + * + * @param file + * The file to check. + * @throws FileNotFoundException + * The exception thrown if the file doesn't exist. + */ + public static void checkExists(File file) throws FileNotFoundException { + if (!file.exists()) { + throw new FileNotFoundException("File: " + + file.getAbsolutePath() + " does not exist"); + } + } + + + /** + * Throws an {@link FileNotFoundException} if any of the files do not exist. + * + * @param files + * The files to check. + * @throws FileNotFoundException + * The exception thrown if any file doesn't exist. + */ + public static void checkExists(File ... files) throws FileNotFoundException { + for (File f : files) { + checkExists(f); + } + } + + + /** + * Makes the directory if it doesn't already exist. Throws an exception if + * there is an error creating the directory. + * + * @param dir + * The directory to create. + * @throws IOException + * If there is an error making the directory. + */ + public static void mkdir(File dir) throws IOException { + if (dir.isDirectory()) { + return; + } + + if (!dir.mkdir()) { + throw new IOException("Unable to create directory"); + } + } + + /** + * Makes the directory if it doesn't already exist. Throws an exception if + * there is an error creating the directory. All intermediate subdirectories + * are also created. + * + * @param dir + * The directory to create. + * @throws IOException + * If there is an error making the directory. + */ + public static void mkdirs(File dir) throws IOException { + if (dir.isDirectory()) { + return; + } + + if (!dir.mkdirs()) { + throw new IOException("Unable to create directory"); + } + } + + + /** + * Create an absolute url for a file. + * + * @param file + * The file. + * @return The url + */ + public static URL createAbsoluteURL(File file) { + File absolute = file.getAbsoluteFile(); + try { + return absolute.toURI().toURL(); + } catch (MalformedURLException e) { + // Shouldn't happen (url cant be malformed, can it?) + return null; + } + } + + /** + * Join a set of path components using the path separator + * + * @param parts + * The path components + * @return The joined path + */ + public static String pathJoin(String ... parts) { + StringBuilder sb = new StringBuilder(); + if (parts.length > 0 && parts[0].startsWith(File.separator)) { + // Assume an absolute path + sb.append(File.separator); + } + + for (String part : parts) { + sb.append(normalizePathComponent(part)); + if (part != parts[parts.length-1]) { + sb.append(File.separatorChar); + } + } + + return sb.toString(); + } + + /** + * Removes leading and trailing path separators from the path component + * + * @param component + * A path component + * @return A stripped string + */ + private static String normalizePathComponent(String component) { + if (component.endsWith(File.separator)) { + component = component.substring(0, File.separator.length()); + } else if (component.startsWith(File.separator)) { + component = component.substring(File.separator.length()); + } else { + return component; + } + return normalizePathComponent(component); + } +} diff --git a/Annotation/src/ie/dcu/util/OsUtils.class b/Annotation/src/ie/dcu/util/OsUtils.class new file mode 100644 index 0000000..a024ef0 Binary files /dev/null and b/Annotation/src/ie/dcu/util/OsUtils.class differ diff --git a/Annotation/src/ie/dcu/util/OsUtils.java b/Annotation/src/ie/dcu/util/OsUtils.java new file mode 100644 index 0000000..45558ea --- /dev/null +++ b/Annotation/src/ie/dcu/util/OsUtils.java @@ -0,0 +1,61 @@ +package ie.dcu.util; + +/** + * Utilities for identifying the operating system. + * + * @author Kevin McGuinness + */ +public class OsUtils { + private static final String OS_NAME = "os.name"; + + /** + * Returns true if the is Mac OS or Mac OS X. + */ + public static boolean isMacOS() { + String os = System.getProperty("os.name"); + os = os.toLowerCase(); + return os.startsWith("mac os"); + } + + /** + * Returns true if the OS is Mac OS X. + */ + public static boolean isMacOSX() { + String os = System.getProperty(OS_NAME); + os = os.toLowerCase(); + return os.startsWith("mac os x"); + } + + /** + * Returns true if the OS is an MS Windows variant. + */ + public static boolean isWindows() { + String os = System.getProperty(OS_NAME); + return os.startsWith("Windows"); + } + + /** + * Returns true if the OS is a Linux variant. + */ + public static boolean isLinux() { + String os = System.getProperty(OS_NAME); + return os.startsWith("Linux"); + } + + /** + * Returns the users home folder. + */ + public static String userHome() { + return System.getProperty("user.home"); + } + + /** + * Returns true if we are on Linux and on a 64 bit Java VM. + * + * Note: this is basically guess-work and depends on the VM vendor. + * Should work for Sun Java though. + */ + public static boolean isLinux64() { + return isLinux() && System.getProperty("os.arch").endsWith("64"); + } +} diff --git a/Annotation/src/ie/dcu/util/PropsUtils.class b/Annotation/src/ie/dcu/util/PropsUtils.class new file mode 100644 index 0000000..a97031c Binary files /dev/null and b/Annotation/src/ie/dcu/util/PropsUtils.class differ diff --git a/Annotation/src/ie/dcu/util/PropsUtils.java b/Annotation/src/ie/dcu/util/PropsUtils.java new file mode 100644 index 0000000..1ded1aa --- /dev/null +++ b/Annotation/src/ie/dcu/util/PropsUtils.java @@ -0,0 +1,71 @@ +package ie.dcu.util; + +import java.io.*; +import java.util.*; + +/** + * Utility functions for .properties files. + * + * @author Kevin McGuinness + */ +public class PropsUtils { + + /** + * Save the properties object to a file. + * + * @param props + * The properties. + * @param file + * The file to save it to. + * @throws IOException + * If there is an error saving. + */ + public static void save(Properties props, File file) throws IOException { + OutputStream out = null; + + try { + out = new BufferedOutputStream(new FileOutputStream(file)); + props.store(out, "Automatically generated properties file"); + + } finally { + + if (out != null) out.close(); + } + } + + + /** + * Load the properties object from a file. + * + * @param file + * The file. + * @return A new properties object. + * @throws IOException + * If an error occurs loading the properties. + */ + public static Properties load(File file) throws IOException { + InputStream in = null; + Properties props = null; + + try { + in = new BufferedInputStream(new FileInputStream(file)); + props = new Properties(); + props.load(in); + + } finally { + + if (in != null) in.close(); + } + + return props; + } + + + public static File getFile(Properties props, String key) { + String val = props.getProperty(key); + if (val != null) { + return new File(val); + } + return null; + } +} diff --git a/Annotation/src/org/eclipse/core/commands/AbstractHandler.class b/Annotation/src/org/eclipse/core/commands/AbstractHandler.class new file mode 100644 index 0000000..fc850b8 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/AbstractHandler.class differ diff --git a/Annotation/src/org/eclipse/core/commands/AbstractHandlerWithState.class b/Annotation/src/org/eclipse/core/commands/AbstractHandlerWithState.class new file mode 100644 index 0000000..fd8a738 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/AbstractHandlerWithState.class differ diff --git a/Annotation/src/org/eclipse/core/commands/AbstractParameterValueConverter.class b/Annotation/src/org/eclipse/core/commands/AbstractParameterValueConverter.class new file mode 100644 index 0000000..cadd9da Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/AbstractParameterValueConverter.class differ diff --git a/Annotation/src/org/eclipse/core/commands/Category.class b/Annotation/src/org/eclipse/core/commands/Category.class new file mode 100644 index 0000000..fd0cd75 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/Category.class differ diff --git a/Annotation/src/org/eclipse/core/commands/CategoryEvent.class b/Annotation/src/org/eclipse/core/commands/CategoryEvent.class new file mode 100644 index 0000000..2ff4b62 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/CategoryEvent.class differ diff --git a/Annotation/src/org/eclipse/core/commands/Command$1.class b/Annotation/src/org/eclipse/core/commands/Command$1.class new file mode 100644 index 0000000..058b9ef Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/Command$1.class differ diff --git a/Annotation/src/org/eclipse/core/commands/Command$2.class b/Annotation/src/org/eclipse/core/commands/Command$2.class new file mode 100644 index 0000000..a6ea8e6 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/Command$2.class differ diff --git a/Annotation/src/org/eclipse/core/commands/Command.class b/Annotation/src/org/eclipse/core/commands/Command.class new file mode 100644 index 0000000..07f1d0f Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/Command.class differ diff --git a/Annotation/src/org/eclipse/core/commands/CommandEvent.class b/Annotation/src/org/eclipse/core/commands/CommandEvent.class new file mode 100644 index 0000000..211b1eb Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/CommandEvent.class differ diff --git a/Annotation/src/org/eclipse/core/commands/CommandManager$ExecutionListener.class b/Annotation/src/org/eclipse/core/commands/CommandManager$ExecutionListener.class new file mode 100644 index 0000000..cfd3c6e Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/CommandManager$ExecutionListener.class differ diff --git a/Annotation/src/org/eclipse/core/commands/CommandManager.class b/Annotation/src/org/eclipse/core/commands/CommandManager.class new file mode 100644 index 0000000..5c994e3 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/CommandManager.class differ diff --git a/Annotation/src/org/eclipse/core/commands/CommandManagerEvent.class b/Annotation/src/org/eclipse/core/commands/CommandManagerEvent.class new file mode 100644 index 0000000..c147db0 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/CommandManagerEvent.class differ diff --git a/Annotation/src/org/eclipse/core/commands/ExecutionEvent.class b/Annotation/src/org/eclipse/core/commands/ExecutionEvent.class new file mode 100644 index 0000000..9588fd5 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/ExecutionEvent.class differ diff --git a/Annotation/src/org/eclipse/core/commands/ExecutionException.class b/Annotation/src/org/eclipse/core/commands/ExecutionException.class new file mode 100644 index 0000000..14c3b56 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/ExecutionException.class differ diff --git a/Annotation/src/org/eclipse/core/commands/HandlerEvent.class b/Annotation/src/org/eclipse/core/commands/HandlerEvent.class new file mode 100644 index 0000000..7733f7a Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/HandlerEvent.class differ diff --git a/Annotation/src/org/eclipse/core/commands/ICategoryListener.class b/Annotation/src/org/eclipse/core/commands/ICategoryListener.class new file mode 100644 index 0000000..2202845 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/ICategoryListener.class differ diff --git a/Annotation/src/org/eclipse/core/commands/ICommandListener.class b/Annotation/src/org/eclipse/core/commands/ICommandListener.class new file mode 100644 index 0000000..d4014ab Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/ICommandListener.class differ diff --git a/Annotation/src/org/eclipse/core/commands/ICommandManagerListener.class b/Annotation/src/org/eclipse/core/commands/ICommandManagerListener.class new file mode 100644 index 0000000..2f307a5 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/ICommandManagerListener.class differ diff --git a/Annotation/src/org/eclipse/core/commands/IExecutionListener.class b/Annotation/src/org/eclipse/core/commands/IExecutionListener.class new file mode 100644 index 0000000..d8b2236 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/IExecutionListener.class differ diff --git a/Annotation/src/org/eclipse/core/commands/IExecutionListenerWithChecks.class b/Annotation/src/org/eclipse/core/commands/IExecutionListenerWithChecks.class new file mode 100644 index 0000000..6ca7e50 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/IExecutionListenerWithChecks.class differ diff --git a/Annotation/src/org/eclipse/core/commands/IHandler.class b/Annotation/src/org/eclipse/core/commands/IHandler.class new file mode 100644 index 0000000..2cc14d6 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/IHandler.class differ diff --git a/Annotation/src/org/eclipse/core/commands/IHandlerAttributes.class b/Annotation/src/org/eclipse/core/commands/IHandlerAttributes.class new file mode 100644 index 0000000..b118cc8 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/IHandlerAttributes.class differ diff --git a/Annotation/src/org/eclipse/core/commands/IHandlerListener.class b/Annotation/src/org/eclipse/core/commands/IHandlerListener.class new file mode 100644 index 0000000..6629aab Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/IHandlerListener.class differ diff --git a/Annotation/src/org/eclipse/core/commands/INamedHandleStateIds.class b/Annotation/src/org/eclipse/core/commands/INamedHandleStateIds.class new file mode 100644 index 0000000..6edcbe0 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/INamedHandleStateIds.class differ diff --git a/Annotation/src/org/eclipse/core/commands/IObjectWithState.class b/Annotation/src/org/eclipse/core/commands/IObjectWithState.class new file mode 100644 index 0000000..a36b10a Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/IObjectWithState.class differ diff --git a/Annotation/src/org/eclipse/core/commands/IParameter.class b/Annotation/src/org/eclipse/core/commands/IParameter.class new file mode 100644 index 0000000..6f34587 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/IParameter.class differ diff --git a/Annotation/src/org/eclipse/core/commands/IParameterTypeListener.class b/Annotation/src/org/eclipse/core/commands/IParameterTypeListener.class new file mode 100644 index 0000000..c9d42d0 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/IParameterTypeListener.class differ diff --git a/Annotation/src/org/eclipse/core/commands/IParameterValues.class b/Annotation/src/org/eclipse/core/commands/IParameterValues.class new file mode 100644 index 0000000..6958a1d Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/IParameterValues.class differ diff --git a/Annotation/src/org/eclipse/core/commands/IStateListener.class b/Annotation/src/org/eclipse/core/commands/IStateListener.class new file mode 100644 index 0000000..0222e95 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/IStateListener.class differ diff --git a/Annotation/src/org/eclipse/core/commands/ITypedParameter.class b/Annotation/src/org/eclipse/core/commands/ITypedParameter.class new file mode 100644 index 0000000..73c7dbc Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/ITypedParameter.class differ diff --git a/Annotation/src/org/eclipse/core/commands/NamedHandleObjectWithState.class b/Annotation/src/org/eclipse/core/commands/NamedHandleObjectWithState.class new file mode 100644 index 0000000..f3d7502 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/NamedHandleObjectWithState.class differ diff --git a/Annotation/src/org/eclipse/core/commands/NotEnabledException.class b/Annotation/src/org/eclipse/core/commands/NotEnabledException.class new file mode 100644 index 0000000..13bd30b Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/NotEnabledException.class differ diff --git a/Annotation/src/org/eclipse/core/commands/NotHandledException.class b/Annotation/src/org/eclipse/core/commands/NotHandledException.class new file mode 100644 index 0000000..bdcc4ef Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/NotHandledException.class differ diff --git a/Annotation/src/org/eclipse/core/commands/ParameterType.class b/Annotation/src/org/eclipse/core/commands/ParameterType.class new file mode 100644 index 0000000..a41fce7 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/ParameterType.class differ diff --git a/Annotation/src/org/eclipse/core/commands/ParameterTypeEvent.class b/Annotation/src/org/eclipse/core/commands/ParameterTypeEvent.class new file mode 100644 index 0000000..b2dad9e Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/ParameterTypeEvent.class differ diff --git a/Annotation/src/org/eclipse/core/commands/ParameterValueConversionException.class b/Annotation/src/org/eclipse/core/commands/ParameterValueConversionException.class new file mode 100644 index 0000000..6e6f050 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/ParameterValueConversionException.class differ diff --git a/Annotation/src/org/eclipse/core/commands/ParameterValuesException.class b/Annotation/src/org/eclipse/core/commands/ParameterValuesException.class new file mode 100644 index 0000000..4a4cdc1 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/ParameterValuesException.class differ diff --git a/Annotation/src/org/eclipse/core/commands/Parameterization.class b/Annotation/src/org/eclipse/core/commands/Parameterization.class new file mode 100644 index 0000000..5e4e28d Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/Parameterization.class differ diff --git a/Annotation/src/org/eclipse/core/commands/ParameterizedCommand.class b/Annotation/src/org/eclipse/core/commands/ParameterizedCommand.class new file mode 100644 index 0000000..7476ce3 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/ParameterizedCommand.class differ diff --git a/Annotation/src/org/eclipse/core/commands/SerializationException.class b/Annotation/src/org/eclipse/core/commands/SerializationException.class new file mode 100644 index 0000000..95f8ebc Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/SerializationException.class differ diff --git a/Annotation/src/org/eclipse/core/commands/State.class b/Annotation/src/org/eclipse/core/commands/State.class new file mode 100644 index 0000000..128c208 Binary files /dev/null and b/Annotation/src/org/eclipse/core/commands/State.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/Binding.class b/Annotation/src/org/eclipse/jface/bindings/Binding.class new file mode 100644 index 0000000..d044cc9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/Binding.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/BindingManager.class b/Annotation/src/org/eclipse/jface/bindings/BindingManager.class new file mode 100644 index 0000000..f7a0a9e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/BindingManager.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/BindingManagerEvent.class b/Annotation/src/org/eclipse/jface/bindings/BindingManagerEvent.class new file mode 100644 index 0000000..3cc6fd8 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/BindingManagerEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/CachedBindingSet.class b/Annotation/src/org/eclipse/jface/bindings/CachedBindingSet.class new file mode 100644 index 0000000..22d0f93 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/CachedBindingSet.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/IBindingManagerListener.class b/Annotation/src/org/eclipse/jface/bindings/IBindingManagerListener.class new file mode 100644 index 0000000..c0a7264 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/IBindingManagerListener.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/ISchemeListener.class b/Annotation/src/org/eclipse/jface/bindings/ISchemeListener.class new file mode 100644 index 0000000..47709d8 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/ISchemeListener.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/Scheme.class b/Annotation/src/org/eclipse/jface/bindings/Scheme.class new file mode 100644 index 0000000..aa16d89 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/Scheme.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/SchemeEvent.class b/Annotation/src/org/eclipse/jface/bindings/SchemeEvent.class new file mode 100644 index 0000000..74fc849 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/SchemeEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/Trigger.class b/Annotation/src/org/eclipse/jface/bindings/Trigger.class new file mode 100644 index 0000000..11a533f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/Trigger.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/TriggerSequence.class b/Annotation/src/org/eclipse/jface/bindings/TriggerSequence.class new file mode 100644 index 0000000..69bb12a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/TriggerSequence.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/IKeyLookup.class b/Annotation/src/org/eclipse/jface/bindings/keys/IKeyLookup.class new file mode 100644 index 0000000..9797341 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/IKeyLookup.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/KeyBinding.class b/Annotation/src/org/eclipse/jface/bindings/keys/KeyBinding.class new file mode 100644 index 0000000..d24d7cf Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/KeyBinding.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/KeyLookupFactory.class b/Annotation/src/org/eclipse/jface/bindings/keys/KeyLookupFactory.class new file mode 100644 index 0000000..3e3eb4b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/KeyLookupFactory.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/KeySequence.class b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequence.class new file mode 100644 index 0000000..60cd052 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequence.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$1.class b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$1.class new file mode 100644 index 0000000..46add71 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$1.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$2.class b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$2.class new file mode 100644 index 0000000..cec7e92 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$2.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$KeyTrapListener.class b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$KeyTrapListener.class new file mode 100644 index 0000000..198ae64 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$KeyTrapListener.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$TraversalFilter.class b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$TraversalFilter.class new file mode 100644 index 0000000..4143a4e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$TraversalFilter.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$TraversalFilterManager.class b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$TraversalFilterManager.class new file mode 100644 index 0000000..7acc7ea Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$TraversalFilterManager.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$UpdateSequenceListener.class b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$UpdateSequenceListener.class new file mode 100644 index 0000000..c0fad2c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText$UpdateSequenceListener.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText.class b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText.class new file mode 100644 index 0000000..79996c0 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/KeySequenceText.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/KeyStroke.class b/Annotation/src/org/eclipse/jface/bindings/keys/KeyStroke.class new file mode 100644 index 0000000..fd4228b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/KeyStroke.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/ParseException.class b/Annotation/src/org/eclipse/jface/bindings/keys/ParseException.class new file mode 100644 index 0000000..7c2f40d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/ParseException.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/SWTKeyLookup.class b/Annotation/src/org/eclipse/jface/bindings/keys/SWTKeyLookup.class new file mode 100644 index 0000000..66663bd Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/SWTKeyLookup.class differ diff --git a/Annotation/src/org/eclipse/jface/bindings/keys/SWTKeySupport.class b/Annotation/src/org/eclipse/jface/bindings/keys/SWTKeySupport.class new file mode 100644 index 0000000..036c546 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/bindings/keys/SWTKeySupport.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/AnimatorFactory.class b/Annotation/src/org/eclipse/jface/dialogs/AnimatorFactory.class new file mode 100644 index 0000000..3c90922 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/AnimatorFactory.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ControlAnimator.class b/Annotation/src/org/eclipse/jface/dialogs/ControlAnimator.class new file mode 100644 index 0000000..6ee3984 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ControlAnimator.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ControlEnableState$ItemState.class b/Annotation/src/org/eclipse/jface/dialogs/ControlEnableState$ItemState.class new file mode 100644 index 0000000..a3e4e3c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ControlEnableState$ItemState.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ControlEnableState.class b/Annotation/src/org/eclipse/jface/dialogs/ControlEnableState.class new file mode 100644 index 0000000..8ea2cbf Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ControlEnableState.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/Dialog$1.class b/Annotation/src/org/eclipse/jface/dialogs/Dialog$1.class new file mode 100644 index 0000000..c627ecf Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/Dialog$1.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/Dialog$2.class b/Annotation/src/org/eclipse/jface/dialogs/Dialog$2.class new file mode 100644 index 0000000..9201b84 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/Dialog$2.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/Dialog.class b/Annotation/src/org/eclipse/jface/dialogs/Dialog.class new file mode 100644 index 0000000..f033864 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/Dialog.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/DialogMessageArea.class b/Annotation/src/org/eclipse/jface/dialogs/DialogMessageArea.class new file mode 100644 index 0000000..ef57ae4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/DialogMessageArea.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/DialogPage.class b/Annotation/src/org/eclipse/jface/dialogs/DialogPage.class new file mode 100644 index 0000000..04332bd Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/DialogPage.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/DialogSettings$XMLWriter.class b/Annotation/src/org/eclipse/jface/dialogs/DialogSettings$XMLWriter.class new file mode 100644 index 0000000..7d1aff6 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/DialogSettings$XMLWriter.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/DialogSettings.class b/Annotation/src/org/eclipse/jface/dialogs/DialogSettings.class new file mode 100644 index 0000000..396757a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/DialogSettings.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/DialogTray.class b/Annotation/src/org/eclipse/jface/dialogs/DialogTray.class new file mode 100644 index 0000000..ed342aa Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/DialogTray.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ErrorDialog$1.class b/Annotation/src/org/eclipse/jface/dialogs/ErrorDialog$1.class new file mode 100644 index 0000000..cabd784 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ErrorDialog$1.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ErrorDialog.class b/Annotation/src/org/eclipse/jface/dialogs/ErrorDialog.class new file mode 100644 index 0000000..46ef1f8 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ErrorDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ErrorSupportProvider.class b/Annotation/src/org/eclipse/jface/dialogs/ErrorSupportProvider.class new file mode 100644 index 0000000..9dbd478 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ErrorSupportProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IDialogBlockedHandler.class b/Annotation/src/org/eclipse/jface/dialogs/IDialogBlockedHandler.class new file mode 100644 index 0000000..6fae5f1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IDialogBlockedHandler.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IDialogConstants.class b/Annotation/src/org/eclipse/jface/dialogs/IDialogConstants.class new file mode 100644 index 0000000..dd4d8c8 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IDialogConstants.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IDialogPage.class b/Annotation/src/org/eclipse/jface/dialogs/IDialogPage.class new file mode 100644 index 0000000..e09f48e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IDialogPage.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IDialogSettings.class b/Annotation/src/org/eclipse/jface/dialogs/IDialogSettings.class new file mode 100644 index 0000000..a90e811 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IDialogSettings.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IInputValidator.class b/Annotation/src/org/eclipse/jface/dialogs/IInputValidator.class new file mode 100644 index 0000000..95973a5 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IInputValidator.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IMessageProvider.class b/Annotation/src/org/eclipse/jface/dialogs/IMessageProvider.class new file mode 100644 index 0000000..58b3966 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IMessageProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IPageChangeProvider.class b/Annotation/src/org/eclipse/jface/dialogs/IPageChangeProvider.class new file mode 100644 index 0000000..9f9ef6c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IPageChangeProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IPageChangedListener.class b/Annotation/src/org/eclipse/jface/dialogs/IPageChangedListener.class new file mode 100644 index 0000000..2a8073d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IPageChangedListener.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IPageChangingListener.class b/Annotation/src/org/eclipse/jface/dialogs/IPageChangingListener.class new file mode 100644 index 0000000..be08d35 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IPageChangingListener.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IconAndMessageDialog$1.class b/Annotation/src/org/eclipse/jface/dialogs/IconAndMessageDialog$1.class new file mode 100644 index 0000000..4741a4d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IconAndMessageDialog$1.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IconAndMessageDialog$2.class b/Annotation/src/org/eclipse/jface/dialogs/IconAndMessageDialog$2.class new file mode 100644 index 0000000..de192a8 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IconAndMessageDialog$2.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/IconAndMessageDialog.class b/Annotation/src/org/eclipse/jface/dialogs/IconAndMessageDialog.class new file mode 100644 index 0000000..a6cd70a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/IconAndMessageDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ImageAndMessageArea$1.class b/Annotation/src/org/eclipse/jface/dialogs/ImageAndMessageArea$1.class new file mode 100644 index 0000000..255e9ce Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ImageAndMessageArea$1.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ImageAndMessageArea$2.class b/Annotation/src/org/eclipse/jface/dialogs/ImageAndMessageArea$2.class new file mode 100644 index 0000000..bf5a6a8 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ImageAndMessageArea$2.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ImageAndMessageArea.class b/Annotation/src/org/eclipse/jface/dialogs/ImageAndMessageArea.class new file mode 100644 index 0000000..3dea9cc Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ImageAndMessageArea.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/InputDialog$1.class b/Annotation/src/org/eclipse/jface/dialogs/InputDialog$1.class new file mode 100644 index 0000000..ac32009 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/InputDialog$1.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/InputDialog.class b/Annotation/src/org/eclipse/jface/dialogs/InputDialog.class new file mode 100644 index 0000000..5ca4728 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/InputDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/MessageDialog.class b/Annotation/src/org/eclipse/jface/dialogs/MessageDialog.class new file mode 100644 index 0000000..c013610 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/MessageDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/MessageDialogWithToggle$1.class b/Annotation/src/org/eclipse/jface/dialogs/MessageDialogWithToggle$1.class new file mode 100644 index 0000000..10455aa Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/MessageDialogWithToggle$1.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/MessageDialogWithToggle.class b/Annotation/src/org/eclipse/jface/dialogs/MessageDialogWithToggle.class new file mode 100644 index 0000000..97d5716 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/MessageDialogWithToggle.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PageChangedEvent.class b/Annotation/src/org/eclipse/jface/dialogs/PageChangedEvent.class new file mode 100644 index 0000000..378b2df Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PageChangedEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PageChangingEvent.class b/Annotation/src/org/eclipse/jface/dialogs/PageChangingEvent.class new file mode 100644 index 0000000..f7f5ffc Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PageChangingEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$1.class b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$1.class new file mode 100644 index 0000000..a55d06d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$1.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$2.class b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$2.class new file mode 100644 index 0000000..ba13b08 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$2.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$3.class b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$3.class new file mode 100644 index 0000000..a0e6206 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$3.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$4.class b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$4.class new file mode 100644 index 0000000..19ff10c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$4.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$5.class b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$5.class new file mode 100644 index 0000000..98c44fd Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$5.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$6.class b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$6.class new file mode 100644 index 0000000..6d18644 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$6.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$7.class b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$7.class new file mode 100644 index 0000000..ad77060 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$7.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$MoveAction.class b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$MoveAction.class new file mode 100644 index 0000000..4929af2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$MoveAction.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$PersistBoundsAction.class b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$PersistBoundsAction.class new file mode 100644 index 0000000..63102b5 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$PersistBoundsAction.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$ResizeAction.class b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$ResizeAction.class new file mode 100644 index 0000000..c3c2e44 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog$ResizeAction.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/PopupDialog.class b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog.class new file mode 100644 index 0000000..2415786 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/PopupDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ProgressIndicator.class b/Annotation/src/org/eclipse/jface/dialogs/ProgressIndicator.class new file mode 100644 index 0000000..90bbed1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ProgressIndicator.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$1.class b/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$1.class new file mode 100644 index 0000000..3bb8e8c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$1.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$2.class b/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$2.class new file mode 100644 index 0000000..c947421 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$2.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$3.class b/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$3.class new file mode 100644 index 0000000..b5e236e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$3.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$ProgressMonitor.class b/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$ProgressMonitor.class new file mode 100644 index 0000000..333dc0e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog$ProgressMonitor.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog.class b/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog.class new file mode 100644 index 0000000..1054160 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/ProgressMonitorDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/StatusDialog$MessageLine.class b/Annotation/src/org/eclipse/jface/dialogs/StatusDialog$MessageLine.class new file mode 100644 index 0000000..50823fb Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/StatusDialog$MessageLine.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/StatusDialog.class b/Annotation/src/org/eclipse/jface/dialogs/StatusDialog.class new file mode 100644 index 0000000..6d147eb Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/StatusDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/TitleAreaDialog$1.class b/Annotation/src/org/eclipse/jface/dialogs/TitleAreaDialog$1.class new file mode 100644 index 0000000..de0712b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/TitleAreaDialog$1.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/TitleAreaDialog.class b/Annotation/src/org/eclipse/jface/dialogs/TitleAreaDialog.class new file mode 100644 index 0000000..9cefb2a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/TitleAreaDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$1.class b/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$1.class new file mode 100644 index 0000000..4dc39db Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$1.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$2.class b/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$2.class new file mode 100644 index 0000000..86e3af4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$2.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$3.class b/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$3.class new file mode 100644 index 0000000..e36dbda Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$3.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$4.class b/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$4.class new file mode 100644 index 0000000..3b1a6d1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/TrayDialog$4.class differ diff --git a/Annotation/src/org/eclipse/jface/dialogs/TrayDialog.class b/Annotation/src/org/eclipse/jface/dialogs/TrayDialog.class new file mode 100644 index 0000000..9e76571 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/dialogs/TrayDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/AutoCompleteField.class b/Annotation/src/org/eclipse/jface/fieldassist/AutoCompleteField.class new file mode 100644 index 0000000..9b89167 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/AutoCompleteField.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ComboContentAdapter.class b/Annotation/src/org/eclipse/jface/fieldassist/ComboContentAdapter.class new file mode 100644 index 0000000..53db91c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ComboContentAdapter.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$1.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$1.class new file mode 100644 index 0000000..b824dcc Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$1.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$10.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$10.class new file mode 100644 index 0000000..f14a8b4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$10.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$11.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$11.class new file mode 100644 index 0000000..210e0a3 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$11.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$12.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$12.class new file mode 100644 index 0000000..aee2769 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$12.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$13.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$13.class new file mode 100644 index 0000000..dce0743 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$13.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$14.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$14.class new file mode 100644 index 0000000..4703e4c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$14.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$2.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$2.class new file mode 100644 index 0000000..72e052e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$2.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$3.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$3.class new file mode 100644 index 0000000..7e536e2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$3.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$4.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$4.class new file mode 100644 index 0000000..88ee86e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$4.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$5.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$5.class new file mode 100644 index 0000000..62f43d9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$5.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$6.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$6.class new file mode 100644 index 0000000..d022c45 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$6.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$7.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$7.class new file mode 100644 index 0000000..55f65b9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$7.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$8.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$8.class new file mode 100644 index 0000000..9d5f41f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$8.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$9.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$9.class new file mode 100644 index 0000000..4354ed6 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$9.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup$InfoPopupDialog.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup$InfoPopupDialog.class new file mode 100644 index 0000000..5930358 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup$InfoPopupDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup$PopupCloserListener.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup$PopupCloserListener.class new file mode 100644 index 0000000..e7c7fe3 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup$PopupCloserListener.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup$TargetControlListener.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup$TargetControlListener.class new file mode 100644 index 0000000..6e1abfb Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup$TargetControlListener.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup.class new file mode 100644 index 0000000..639539f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter$ContentProposalPopup.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter.class b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter.class new file mode 100644 index 0000000..59350df Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ContentProposalAdapter.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$1.class b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$1.class new file mode 100644 index 0000000..2c5daff Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$1.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$2.class b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$2.class new file mode 100644 index 0000000..b4e7489 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$2.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$3.class b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$3.class new file mode 100644 index 0000000..d8494b2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$3.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$4.class b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$4.class new file mode 100644 index 0000000..7db6078 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$4.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$5.class b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$5.class new file mode 100644 index 0000000..8a7b014 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$5.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$6.class b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$6.class new file mode 100644 index 0000000..b35767f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$6.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$7.class b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$7.class new file mode 100644 index 0000000..18d711f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$7.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$8.class b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$8.class new file mode 100644 index 0000000..ad02bf5 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$8.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$Hover.class b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$Hover.class new file mode 100644 index 0000000..218d027 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration$Hover.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration.class b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration.class new file mode 100644 index 0000000..7ae26ed Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/ControlDecoration.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$1.class b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$1.class new file mode 100644 index 0000000..45c7c7d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$1.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$2.class b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$2.class new file mode 100644 index 0000000..85c252b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$2.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$3.class b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$3.class new file mode 100644 index 0000000..3443fe2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$3.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$4.class b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$4.class new file mode 100644 index 0000000..f007039 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$4.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$5.class b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$5.class new file mode 100644 index 0000000..511a721 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$5.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$FieldDecorationData.class b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$FieldDecorationData.class new file mode 100644 index 0000000..48178e6 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$FieldDecorationData.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$Hover.class b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$Hover.class new file mode 100644 index 0000000..a54f58d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField$Hover.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField.class b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField.class new file mode 100644 index 0000000..d407d50 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/DecoratedField.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/FieldAssistColors$1.class b/Annotation/src/org/eclipse/jface/fieldassist/FieldAssistColors$1.class new file mode 100644 index 0000000..0790ff8 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/FieldAssistColors$1.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/FieldAssistColors.class b/Annotation/src/org/eclipse/jface/fieldassist/FieldAssistColors.class new file mode 100644 index 0000000..59eff2d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/FieldAssistColors.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/FieldDecoration.class b/Annotation/src/org/eclipse/jface/fieldassist/FieldDecoration.class new file mode 100644 index 0000000..23e5cf2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/FieldDecoration.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/FieldDecorationRegistry$Entry.class b/Annotation/src/org/eclipse/jface/fieldassist/FieldDecorationRegistry$Entry.class new file mode 100644 index 0000000..0160db4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/FieldDecorationRegistry$Entry.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/FieldDecorationRegistry.class b/Annotation/src/org/eclipse/jface/fieldassist/FieldDecorationRegistry.class new file mode 100644 index 0000000..57f3690 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/FieldDecorationRegistry.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/IContentProposal.class b/Annotation/src/org/eclipse/jface/fieldassist/IContentProposal.class new file mode 100644 index 0000000..cba8f79 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/IContentProposal.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/IContentProposalListener.class b/Annotation/src/org/eclipse/jface/fieldassist/IContentProposalListener.class new file mode 100644 index 0000000..830168a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/IContentProposalListener.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/IContentProposalListener2.class b/Annotation/src/org/eclipse/jface/fieldassist/IContentProposalListener2.class new file mode 100644 index 0000000..aa5ed94 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/IContentProposalListener2.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/IContentProposalProvider.class b/Annotation/src/org/eclipse/jface/fieldassist/IContentProposalProvider.class new file mode 100644 index 0000000..0d8da3d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/IContentProposalProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/IControlContentAdapter.class b/Annotation/src/org/eclipse/jface/fieldassist/IControlContentAdapter.class new file mode 100644 index 0000000..812b7c7 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/IControlContentAdapter.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/IControlCreator.class b/Annotation/src/org/eclipse/jface/fieldassist/IControlCreator.class new file mode 100644 index 0000000..7286a2f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/IControlCreator.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/SimpleContentProposalProvider$1.class b/Annotation/src/org/eclipse/jface/fieldassist/SimpleContentProposalProvider$1.class new file mode 100644 index 0000000..409d9d9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/SimpleContentProposalProvider$1.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/SimpleContentProposalProvider.class b/Annotation/src/org/eclipse/jface/fieldassist/SimpleContentProposalProvider.class new file mode 100644 index 0000000..0d39f34 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/SimpleContentProposalProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/TextContentAdapter.class b/Annotation/src/org/eclipse/jface/fieldassist/TextContentAdapter.class new file mode 100644 index 0000000..9b8ed03 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/TextContentAdapter.class differ diff --git a/Annotation/src/org/eclipse/jface/fieldassist/TextControlCreator.class b/Annotation/src/org/eclipse/jface/fieldassist/TextControlCreator.class new file mode 100644 index 0000000..35ffa7d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/fieldassist/TextControlCreator.class differ diff --git a/Annotation/src/org/eclipse/jface/internal/InternalPolicy.class b/Annotation/src/org/eclipse/jface/internal/InternalPolicy.class new file mode 100644 index 0000000..55053bd Binary files /dev/null and b/Annotation/src/org/eclipse/jface/internal/InternalPolicy.class differ diff --git a/Annotation/src/org/eclipse/jface/internal/JFaceActivator.class b/Annotation/src/org/eclipse/jface/internal/JFaceActivator.class new file mode 100644 index 0000000..452d5ad Binary files /dev/null and b/Annotation/src/org/eclipse/jface/internal/JFaceActivator.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/BooleanFieldEditor$1.class b/Annotation/src/org/eclipse/jface/preference/BooleanFieldEditor$1.class new file mode 100644 index 0000000..cbc83a6 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/BooleanFieldEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/BooleanFieldEditor$2.class b/Annotation/src/org/eclipse/jface/preference/BooleanFieldEditor$2.class new file mode 100644 index 0000000..ca34c7c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/BooleanFieldEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/BooleanFieldEditor.class b/Annotation/src/org/eclipse/jface/preference/BooleanFieldEditor.class new file mode 100644 index 0000000..16a7037 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/BooleanFieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/BooleanPropertyAction$1.class b/Annotation/src/org/eclipse/jface/preference/BooleanPropertyAction$1.class new file mode 100644 index 0000000..f2ff48e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/BooleanPropertyAction$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/BooleanPropertyAction.class b/Annotation/src/org/eclipse/jface/preference/BooleanPropertyAction.class new file mode 100644 index 0000000..987c978 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/BooleanPropertyAction.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ColorFieldEditor$1.class b/Annotation/src/org/eclipse/jface/preference/ColorFieldEditor$1.class new file mode 100644 index 0000000..08cef32 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ColorFieldEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ColorFieldEditor.class b/Annotation/src/org/eclipse/jface/preference/ColorFieldEditor.class new file mode 100644 index 0000000..04a3b2a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ColorFieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ColorSelector$1.class b/Annotation/src/org/eclipse/jface/preference/ColorSelector$1.class new file mode 100644 index 0000000..e08d3c1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ColorSelector$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ColorSelector$2.class b/Annotation/src/org/eclipse/jface/preference/ColorSelector$2.class new file mode 100644 index 0000000..6ea3401 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ColorSelector$2.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ColorSelector$3.class b/Annotation/src/org/eclipse/jface/preference/ColorSelector$3.class new file mode 100644 index 0000000..271a8b4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ColorSelector$3.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ColorSelector.class b/Annotation/src/org/eclipse/jface/preference/ColorSelector.class new file mode 100644 index 0000000..ca0b370 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ColorSelector.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ComboFieldEditor$1.class b/Annotation/src/org/eclipse/jface/preference/ComboFieldEditor$1.class new file mode 100644 index 0000000..b9c8218 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ComboFieldEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ComboFieldEditor.class b/Annotation/src/org/eclipse/jface/preference/ComboFieldEditor.class new file mode 100644 index 0000000..26a7495 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ComboFieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/DirectoryFieldEditor.class b/Annotation/src/org/eclipse/jface/preference/DirectoryFieldEditor.class new file mode 100644 index 0000000..62b3239 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/DirectoryFieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/FieldEditor$1.class b/Annotation/src/org/eclipse/jface/preference/FieldEditor$1.class new file mode 100644 index 0000000..b35285d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/FieldEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/FieldEditor.class b/Annotation/src/org/eclipse/jface/preference/FieldEditor.class new file mode 100644 index 0000000..52691ee Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/FieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/FieldEditorPreferencePage.class b/Annotation/src/org/eclipse/jface/preference/FieldEditorPreferencePage.class new file mode 100644 index 0000000..0abc87a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/FieldEditorPreferencePage.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/FileFieldEditor.class b/Annotation/src/org/eclipse/jface/preference/FileFieldEditor.class new file mode 100644 index 0000000..f613daf Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/FileFieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$1.class b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$1.class new file mode 100644 index 0000000..c292227 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$2.class b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$2.class new file mode 100644 index 0000000..9ff0989 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$3.class b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$3.class new file mode 100644 index 0000000..28519e0 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$3.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$4.class b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$4.class new file mode 100644 index 0000000..f40bdff Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$4.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$DefaultPreviewer.class b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$DefaultPreviewer.class new file mode 100644 index 0000000..44557c1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor$DefaultPreviewer.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/FontFieldEditor.class b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor.class new file mode 100644 index 0000000..8e8322c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/FontFieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/IPersistentPreferenceStore.class b/Annotation/src/org/eclipse/jface/preference/IPersistentPreferenceStore.class new file mode 100644 index 0000000..e82e311 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/IPersistentPreferenceStore.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/IPreferenceNode.class b/Annotation/src/org/eclipse/jface/preference/IPreferenceNode.class new file mode 100644 index 0000000..0813d3a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/IPreferenceNode.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/IPreferencePage.class b/Annotation/src/org/eclipse/jface/preference/IPreferencePage.class new file mode 100644 index 0000000..6b6a51b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/IPreferencePage.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/IPreferencePageContainer.class b/Annotation/src/org/eclipse/jface/preference/IPreferencePageContainer.class new file mode 100644 index 0000000..79dd4e9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/IPreferencePageContainer.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/IPreferenceStore.class b/Annotation/src/org/eclipse/jface/preference/IPreferenceStore.class new file mode 100644 index 0000000..47184c4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/IPreferenceStore.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/IntegerFieldEditor.class b/Annotation/src/org/eclipse/jface/preference/IntegerFieldEditor.class new file mode 100644 index 0000000..21ffd68 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/IntegerFieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/JFacePreferences.class b/Annotation/src/org/eclipse/jface/preference/JFacePreferences.class new file mode 100644 index 0000000..c1cca33 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/JFacePreferences.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ListEditor$1.class b/Annotation/src/org/eclipse/jface/preference/ListEditor$1.class new file mode 100644 index 0000000..dd50193 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ListEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ListEditor$2.class b/Annotation/src/org/eclipse/jface/preference/ListEditor$2.class new file mode 100644 index 0000000..dc8c62a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ListEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ListEditor$3.class b/Annotation/src/org/eclipse/jface/preference/ListEditor$3.class new file mode 100644 index 0000000..1239c09 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ListEditor$3.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ListEditor.class b/Annotation/src/org/eclipse/jface/preference/ListEditor.class new file mode 100644 index 0000000..99104e8 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ListEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PathEditor.class b/Annotation/src/org/eclipse/jface/preference/PathEditor.class new file mode 100644 index 0000000..a1db579 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PathEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceContentProvider.class b/Annotation/src/org/eclipse/jface/preference/PreferenceContentProvider.class new file mode 100644 index 0000000..1bab969 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceContentProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceConverter.class b/Annotation/src/org/eclipse/jface/preference/PreferenceConverter.class new file mode 100644 index 0000000..2ad40c4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceConverter.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$1.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$1.class new file mode 100644 index 0000000..53ad119 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$10.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$10.class new file mode 100644 index 0000000..d7a250c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$10.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$11.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$11.class new file mode 100644 index 0000000..420b691 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$11.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$12.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$12.class new file mode 100644 index 0000000..318846e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$12.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$13.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$13.class new file mode 100644 index 0000000..b53ffc9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$13.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$14.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$14.class new file mode 100644 index 0000000..4ca47d6 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$14.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$15.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$15.class new file mode 100644 index 0000000..150f5b2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$15.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$2.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$2.class new file mode 100644 index 0000000..8e84a00 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$2.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$3.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$3.class new file mode 100644 index 0000000..e4e5a91 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$3.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$4.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$4.class new file mode 100644 index 0000000..623cd85 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$4.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$5.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$5.class new file mode 100644 index 0000000..4cc8abb Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$5.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$6.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$6.class new file mode 100644 index 0000000..87c7dcf Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$6.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$7.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$7.class new file mode 100644 index 0000000..6d8854f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$7.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$8.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$8.class new file mode 100644 index 0000000..e7ec5fd Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$8.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$9.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$9.class new file mode 100644 index 0000000..af6bf4b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$9.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$PageLayout.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$PageLayout.class new file mode 100644 index 0000000..7e7394d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog$PageLayout.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceDialog.class b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog.class new file mode 100644 index 0000000..cccb55d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceLabelProvider.class b/Annotation/src/org/eclipse/jface/preference/PreferenceLabelProvider.class new file mode 100644 index 0000000..834cda0 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceManager.class b/Annotation/src/org/eclipse/jface/preference/PreferenceManager.class new file mode 100644 index 0000000..a6a29b0 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceManager.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceNode.class b/Annotation/src/org/eclipse/jface/preference/PreferenceNode.class new file mode 100644 index 0000000..9330d00 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceNode.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferencePage$1.class b/Annotation/src/org/eclipse/jface/preference/PreferencePage$1.class new file mode 100644 index 0000000..2b856aa Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferencePage$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferencePage$2.class b/Annotation/src/org/eclipse/jface/preference/PreferencePage$2.class new file mode 100644 index 0000000..7d4cb7a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferencePage$2.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferencePage$3.class b/Annotation/src/org/eclipse/jface/preference/PreferencePage$3.class new file mode 100644 index 0000000..fbc511f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferencePage$3.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferencePage$4.class b/Annotation/src/org/eclipse/jface/preference/PreferencePage$4.class new file mode 100644 index 0000000..2bf4bb4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferencePage$4.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferencePage.class b/Annotation/src/org/eclipse/jface/preference/PreferencePage.class new file mode 100644 index 0000000..9b04c37 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferencePage.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceStore$1.class b/Annotation/src/org/eclipse/jface/preference/PreferenceStore$1.class new file mode 100644 index 0000000..2a1eb41 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceStore$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/PreferenceStore.class b/Annotation/src/org/eclipse/jface/preference/PreferenceStore.class new file mode 100644 index 0000000..5a99b8f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/PreferenceStore.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/RadioGroupFieldEditor$1.class b/Annotation/src/org/eclipse/jface/preference/RadioGroupFieldEditor$1.class new file mode 100644 index 0000000..bcce391 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/RadioGroupFieldEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/RadioGroupFieldEditor$2.class b/Annotation/src/org/eclipse/jface/preference/RadioGroupFieldEditor$2.class new file mode 100644 index 0000000..3ed0f08 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/RadioGroupFieldEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/RadioGroupFieldEditor.class b/Annotation/src/org/eclipse/jface/preference/RadioGroupFieldEditor.class new file mode 100644 index 0000000..9d84f73 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/RadioGroupFieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ScaleFieldEditor$1.class b/Annotation/src/org/eclipse/jface/preference/ScaleFieldEditor$1.class new file mode 100644 index 0000000..04e2373 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ScaleFieldEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ScaleFieldEditor$2.class b/Annotation/src/org/eclipse/jface/preference/ScaleFieldEditor$2.class new file mode 100644 index 0000000..4b3412e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ScaleFieldEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/ScaleFieldEditor.class b/Annotation/src/org/eclipse/jface/preference/ScaleFieldEditor.class new file mode 100644 index 0000000..d3f936c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/ScaleFieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/StringButtonFieldEditor$1.class b/Annotation/src/org/eclipse/jface/preference/StringButtonFieldEditor$1.class new file mode 100644 index 0000000..37ac228 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/StringButtonFieldEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/StringButtonFieldEditor$2.class b/Annotation/src/org/eclipse/jface/preference/StringButtonFieldEditor$2.class new file mode 100644 index 0000000..fda2d7b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/StringButtonFieldEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/StringButtonFieldEditor.class b/Annotation/src/org/eclipse/jface/preference/StringButtonFieldEditor.class new file mode 100644 index 0000000..47328bb Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/StringButtonFieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$1.class b/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$1.class new file mode 100644 index 0000000..779eb17 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$2.class b/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$2.class new file mode 100644 index 0000000..3877f15 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$3.class b/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$3.class new file mode 100644 index 0000000..7465f58 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$3.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$4.class b/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$4.class new file mode 100644 index 0000000..384af70 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/StringFieldEditor$4.class differ diff --git a/Annotation/src/org/eclipse/jface/preference/StringFieldEditor.class b/Annotation/src/org/eclipse/jface/preference/StringFieldEditor.class new file mode 100644 index 0000000..bcf7808 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/preference/StringFieldEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractListViewer$1.class b/Annotation/src/org/eclipse/jface/viewers/AbstractListViewer$1.class new file mode 100644 index 0000000..8cf84e3 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractListViewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractListViewer.class b/Annotation/src/org/eclipse/jface/viewers/AbstractListViewer.class new file mode 100644 index 0000000..08f293c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractListViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$1.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$1.class new file mode 100644 index 0000000..962d7b9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$2.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$2.class new file mode 100644 index 0000000..11dd2ee Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$3.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$3.class new file mode 100644 index 0000000..a2d890e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$VirtualManager.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$VirtualManager.class new file mode 100644 index 0000000..b76d33d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer$VirtualManager.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer.class new file mode 100644 index 0000000..120409f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTableViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$1.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$1.class new file mode 100644 index 0000000..b4dd9eb Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$2.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$2.class new file mode 100644 index 0000000..0e8957d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$3.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$3.class new file mode 100644 index 0000000..f20e204 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$4.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$4.class new file mode 100644 index 0000000..30d1313 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$4.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$5.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$5.class new file mode 100644 index 0000000..a2e6566 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$5.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$6.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$6.class new file mode 100644 index 0000000..ba98ac2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$6.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$7.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$7.class new file mode 100644 index 0000000..74e31e9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$7.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$8.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$8.class new file mode 100644 index 0000000..dd77079 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$8.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$UpdateItemSafeRunnable.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$UpdateItemSafeRunnable.class new file mode 100644 index 0000000..c7400c2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer$UpdateItemSafeRunnable.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer.class b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer.class new file mode 100644 index 0000000..decfa1c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AbstractTreeViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/AcceptAllFilter.class b/Annotation/src/org/eclipse/jface/viewers/AcceptAllFilter.class new file mode 100644 index 0000000..b29e36a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/AcceptAllFilter.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ArrayContentProvider.class b/Annotation/src/org/eclipse/jface/viewers/ArrayContentProvider.class new file mode 100644 index 0000000..d5f9e27 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ArrayContentProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/BaseLabelProvider$1.class b/Annotation/src/org/eclipse/jface/viewers/BaseLabelProvider$1.class new file mode 100644 index 0000000..6964d8f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/BaseLabelProvider$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/BaseLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/BaseLabelProvider.class new file mode 100644 index 0000000..032547e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/BaseLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CellEditor$1.class b/Annotation/src/org/eclipse/jface/viewers/CellEditor$1.class new file mode 100644 index 0000000..1bb8d46 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CellEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CellEditor$2.class b/Annotation/src/org/eclipse/jface/viewers/CellEditor$2.class new file mode 100644 index 0000000..072d9ef Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CellEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CellEditor$3.class b/Annotation/src/org/eclipse/jface/viewers/CellEditor$3.class new file mode 100644 index 0000000..07f34ac Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CellEditor$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CellEditor$4.class b/Annotation/src/org/eclipse/jface/viewers/CellEditor$4.class new file mode 100644 index 0000000..78078d6 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CellEditor$4.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CellEditor$LayoutData.class b/Annotation/src/org/eclipse/jface/viewers/CellEditor$LayoutData.class new file mode 100644 index 0000000..82b1af3 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CellEditor$LayoutData.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CellEditor.class b/Annotation/src/org/eclipse/jface/viewers/CellEditor.class new file mode 100644 index 0000000..aa4900f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CellEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CellLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/CellLabelProvider.class new file mode 100644 index 0000000..95fb75d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CellLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CellNavigationStrategy.class b/Annotation/src/org/eclipse/jface/viewers/CellNavigationStrategy.class new file mode 100644 index 0000000..2e6c39e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CellNavigationStrategy.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CheckStateChangedEvent.class b/Annotation/src/org/eclipse/jface/viewers/CheckStateChangedEvent.class new file mode 100644 index 0000000..5603a73 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CheckStateChangedEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CheckboxCellEditor.class b/Annotation/src/org/eclipse/jface/viewers/CheckboxCellEditor.class new file mode 100644 index 0000000..2551188 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CheckboxCellEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CheckboxTableViewer$1.class b/Annotation/src/org/eclipse/jface/viewers/CheckboxTableViewer$1.class new file mode 100644 index 0000000..fea876b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CheckboxTableViewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CheckboxTableViewer.class b/Annotation/src/org/eclipse/jface/viewers/CheckboxTableViewer.class new file mode 100644 index 0000000..8891919 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CheckboxTableViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CheckboxTreeViewer$1.class b/Annotation/src/org/eclipse/jface/viewers/CheckboxTreeViewer$1.class new file mode 100644 index 0000000..8dce48f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CheckboxTreeViewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CheckboxTreeViewer.class b/Annotation/src/org/eclipse/jface/viewers/CheckboxTreeViewer.class new file mode 100644 index 0000000..c152f49 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CheckboxTreeViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColorCellEditor$ColorCellLayout.class b/Annotation/src/org/eclipse/jface/viewers/ColorCellEditor$ColorCellLayout.class new file mode 100644 index 0000000..760fa1f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColorCellEditor$ColorCellLayout.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColorCellEditor.class b/Annotation/src/org/eclipse/jface/viewers/ColorCellEditor.class new file mode 100644 index 0000000..3bd23a4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColorCellEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/ColumnLabelProvider.class new file mode 100644 index 0000000..99fd61e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnLayoutData.class b/Annotation/src/org/eclipse/jface/viewers/ColumnLayoutData.class new file mode 100644 index 0000000..827afd1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnLayoutData.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnPixelData.class b/Annotation/src/org/eclipse/jface/viewers/ColumnPixelData.class new file mode 100644 index 0000000..6b16156 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnPixelData.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewer$1.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewer$1.class new file mode 100644 index 0000000..8d4b3e6 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewer$2.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewer$2.class new file mode 100644 index 0000000..02bef7f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewer$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewer$3.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewer$3.class new file mode 100644 index 0000000..039e877 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewer$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewer.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewer.class new file mode 100644 index 0000000..0107596 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$1.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$1.class new file mode 100644 index 0000000..2cfda3a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$2.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$2.class new file mode 100644 index 0000000..ae866c7 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$3.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$3.class new file mode 100644 index 0000000..c760f0b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$4.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$4.class new file mode 100644 index 0000000..70b3819 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor$4.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor.class new file mode 100644 index 0000000..a29c9e3 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationEvent.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationEvent.class new file mode 100644 index 0000000..82a8d7f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationListener.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationListener.class new file mode 100644 index 0000000..c0ad51e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationListener.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationStrategy$1.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationStrategy$1.class new file mode 100644 index 0000000..9144e3e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationStrategy$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationStrategy.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationStrategy.class new file mode 100644 index 0000000..92a59df Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorActivationStrategy.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorDeactivationEvent.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorDeactivationEvent.class new file mode 100644 index 0000000..2aea3ea Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerEditorDeactivationEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnViewerToolTipSupport.class b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerToolTipSupport.class new file mode 100644 index 0000000..18321c6 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnViewerToolTipSupport.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ColumnWeightData.class b/Annotation/src/org/eclipse/jface/viewers/ColumnWeightData.class new file mode 100644 index 0000000..3eda5fa Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ColumnWeightData.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$1.class b/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$1.class new file mode 100644 index 0000000..3baa994 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$2.class b/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$2.class new file mode 100644 index 0000000..f4c1497 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$3.class b/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$3.class new file mode 100644 index 0000000..6806a72 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$4.class b/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$4.class new file mode 100644 index 0000000..9e747ea Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor$4.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor.class b/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor.class new file mode 100644 index 0000000..c959445 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ComboBoxCellEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ComboViewer.class b/Annotation/src/org/eclipse/jface/viewers/ComboViewer.class new file mode 100644 index 0000000..5109aa8 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ComboViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ContentViewer$1.class b/Annotation/src/org/eclipse/jface/viewers/ContentViewer$1.class new file mode 100644 index 0000000..ae57115 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ContentViewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ContentViewer$2.class b/Annotation/src/org/eclipse/jface/viewers/ContentViewer$2.class new file mode 100644 index 0000000..0d526fa Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ContentViewer$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ContentViewer.class b/Annotation/src/org/eclipse/jface/viewers/ContentViewer.class new file mode 100644 index 0000000..d4f4179 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ContentViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CustomHashtable$EmptyEnumerator.class b/Annotation/src/org/eclipse/jface/viewers/CustomHashtable$EmptyEnumerator.class new file mode 100644 index 0000000..f820ba1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CustomHashtable$EmptyEnumerator.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CustomHashtable$HashEnumerator.class b/Annotation/src/org/eclipse/jface/viewers/CustomHashtable$HashEnumerator.class new file mode 100644 index 0000000..230b9bb Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CustomHashtable$HashEnumerator.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CustomHashtable$HashMapEntry.class b/Annotation/src/org/eclipse/jface/viewers/CustomHashtable$HashMapEntry.class new file mode 100644 index 0000000..34bee2b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CustomHashtable$HashMapEntry.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/CustomHashtable.class b/Annotation/src/org/eclipse/jface/viewers/CustomHashtable.class new file mode 100644 index 0000000..ef67732 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/CustomHashtable.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/DecoratingLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/DecoratingLabelProvider.class new file mode 100644 index 0000000..31f1eda Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/DecoratingLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/DecorationContext.class b/Annotation/src/org/eclipse/jface/viewers/DecorationContext.class new file mode 100644 index 0000000..9b05054 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/DecorationContext.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/DecorationOverlayIcon.class b/Annotation/src/org/eclipse/jface/viewers/DecorationOverlayIcon.class new file mode 100644 index 0000000..1041b1b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/DecorationOverlayIcon.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$1.class b/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$1.class new file mode 100644 index 0000000..9edc676 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$2.class b/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$2.class new file mode 100644 index 0000000..2deff8f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$3.class b/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$3.class new file mode 100644 index 0000000..54b3d6a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$DialogCellLayout.class b/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$DialogCellLayout.class new file mode 100644 index 0000000..fa07760 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor$DialogCellLayout.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor.class b/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor.class new file mode 100644 index 0000000..9cf7294 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/DialogCellEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/DoubleClickEvent.class b/Annotation/src/org/eclipse/jface/viewers/DoubleClickEvent.class new file mode 100644 index 0000000..2004d3e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/DoubleClickEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/EditingSupport.class b/Annotation/src/org/eclipse/jface/viewers/EditingSupport.class new file mode 100644 index 0000000..877743c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/EditingSupport.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/FocusCellHighlighter.class b/Annotation/src/org/eclipse/jface/viewers/FocusCellHighlighter.class new file mode 100644 index 0000000..21febb1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/FocusCellHighlighter.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/FocusCellOwnerDrawHighlighter$1.class b/Annotation/src/org/eclipse/jface/viewers/FocusCellOwnerDrawHighlighter$1.class new file mode 100644 index 0000000..aa6a8d5 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/FocusCellOwnerDrawHighlighter$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/FocusCellOwnerDrawHighlighter.class b/Annotation/src/org/eclipse/jface/viewers/FocusCellOwnerDrawHighlighter.class new file mode 100644 index 0000000..440c081 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/FocusCellOwnerDrawHighlighter.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IBaseLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/IBaseLabelProvider.class new file mode 100644 index 0000000..0e4c8fc Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IBaseLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IBasicPropertyConstants.class b/Annotation/src/org/eclipse/jface/viewers/IBasicPropertyConstants.class new file mode 100644 index 0000000..ee723c3 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IBasicPropertyConstants.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ICellEditorListener.class b/Annotation/src/org/eclipse/jface/viewers/ICellEditorListener.class new file mode 100644 index 0000000..25b8fc5 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ICellEditorListener.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ICellEditorValidator.class b/Annotation/src/org/eclipse/jface/viewers/ICellEditorValidator.class new file mode 100644 index 0000000..374ea80 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ICellEditorValidator.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ICellModifier.class b/Annotation/src/org/eclipse/jface/viewers/ICellModifier.class new file mode 100644 index 0000000..0dc7de9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ICellModifier.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ICheckStateListener.class b/Annotation/src/org/eclipse/jface/viewers/ICheckStateListener.class new file mode 100644 index 0000000..4c92f50 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ICheckStateListener.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ICheckable.class b/Annotation/src/org/eclipse/jface/viewers/ICheckable.class new file mode 100644 index 0000000..422cd20 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ICheckable.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IColorDecorator.class b/Annotation/src/org/eclipse/jface/viewers/IColorDecorator.class new file mode 100644 index 0000000..b85b087 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IColorDecorator.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IColorProvider.class b/Annotation/src/org/eclipse/jface/viewers/IColorProvider.class new file mode 100644 index 0000000..6014cc6 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IColorProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IContentProvider.class b/Annotation/src/org/eclipse/jface/viewers/IContentProvider.class new file mode 100644 index 0000000..885bad4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IContentProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IDecoration.class b/Annotation/src/org/eclipse/jface/viewers/IDecoration.class new file mode 100644 index 0000000..39afe8e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IDecoration.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IDecorationContext.class b/Annotation/src/org/eclipse/jface/viewers/IDecorationContext.class new file mode 100644 index 0000000..6291bce Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IDecorationContext.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IDelayedLabelDecorator.class b/Annotation/src/org/eclipse/jface/viewers/IDelayedLabelDecorator.class new file mode 100644 index 0000000..8a2e0d0 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IDelayedLabelDecorator.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IDoubleClickListener.class b/Annotation/src/org/eclipse/jface/viewers/IDoubleClickListener.class new file mode 100644 index 0000000..d52178f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IDoubleClickListener.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IElementComparer.class b/Annotation/src/org/eclipse/jface/viewers/IElementComparer.class new file mode 100644 index 0000000..b469bce Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IElementComparer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IFilter.class b/Annotation/src/org/eclipse/jface/viewers/IFilter.class new file mode 100644 index 0000000..75ef315 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IFilter.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IFontDecorator.class b/Annotation/src/org/eclipse/jface/viewers/IFontDecorator.class new file mode 100644 index 0000000..c676029 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IFontDecorator.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IFontProvider.class b/Annotation/src/org/eclipse/jface/viewers/IFontProvider.class new file mode 100644 index 0000000..1fee662 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IFontProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IInputProvider.class b/Annotation/src/org/eclipse/jface/viewers/IInputProvider.class new file mode 100644 index 0000000..c660d5b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IInputProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IInputSelectionProvider.class b/Annotation/src/org/eclipse/jface/viewers/IInputSelectionProvider.class new file mode 100644 index 0000000..9ce7929 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IInputSelectionProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ILabelDecorator.class b/Annotation/src/org/eclipse/jface/viewers/ILabelDecorator.class new file mode 100644 index 0000000..2bd92b1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ILabelDecorator.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ILabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/ILabelProvider.class new file mode 100644 index 0000000..ebe905f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ILabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ILabelProviderListener.class b/Annotation/src/org/eclipse/jface/viewers/ILabelProviderListener.class new file mode 100644 index 0000000..eca9cd7 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ILabelProviderListener.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ILazyContentProvider.class b/Annotation/src/org/eclipse/jface/viewers/ILazyContentProvider.class new file mode 100644 index 0000000..ae0a63e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ILazyContentProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ILazyTreeContentProvider.class b/Annotation/src/org/eclipse/jface/viewers/ILazyTreeContentProvider.class new file mode 100644 index 0000000..0f4053e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ILazyTreeContentProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ILazyTreePathContentProvider.class b/Annotation/src/org/eclipse/jface/viewers/ILazyTreePathContentProvider.class new file mode 100644 index 0000000..4eb5eee Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ILazyTreePathContentProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ILightweightLabelDecorator.class b/Annotation/src/org/eclipse/jface/viewers/ILightweightLabelDecorator.class new file mode 100644 index 0000000..307a0f1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ILightweightLabelDecorator.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IOpenListener.class b/Annotation/src/org/eclipse/jface/viewers/IOpenListener.class new file mode 100644 index 0000000..25bbdd1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IOpenListener.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IPostSelectionProvider.class b/Annotation/src/org/eclipse/jface/viewers/IPostSelectionProvider.class new file mode 100644 index 0000000..9f55853 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IPostSelectionProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ISelection.class b/Annotation/src/org/eclipse/jface/viewers/ISelection.class new file mode 100644 index 0000000..c245e43 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ISelection.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ISelectionChangedListener.class b/Annotation/src/org/eclipse/jface/viewers/ISelectionChangedListener.class new file mode 100644 index 0000000..4b43eb3 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ISelectionChangedListener.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ISelectionProvider.class b/Annotation/src/org/eclipse/jface/viewers/ISelectionProvider.class new file mode 100644 index 0000000..4736d63 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ISelectionProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IStructuredContentProvider.class b/Annotation/src/org/eclipse/jface/viewers/IStructuredContentProvider.class new file mode 100644 index 0000000..5a72211 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IStructuredContentProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IStructuredSelection.class b/Annotation/src/org/eclipse/jface/viewers/IStructuredSelection.class new file mode 100644 index 0000000..03dbd1a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IStructuredSelection.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ITableColorProvider.class b/Annotation/src/org/eclipse/jface/viewers/ITableColorProvider.class new file mode 100644 index 0000000..808f14a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ITableColorProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ITableFontProvider.class b/Annotation/src/org/eclipse/jface/viewers/ITableFontProvider.class new file mode 100644 index 0000000..c767520 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ITableFontProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ITableLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/ITableLabelProvider.class new file mode 100644 index 0000000..1638ace Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ITableLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ITreeContentProvider.class b/Annotation/src/org/eclipse/jface/viewers/ITreeContentProvider.class new file mode 100644 index 0000000..a992263 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ITreeContentProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ITreePathContentProvider.class b/Annotation/src/org/eclipse/jface/viewers/ITreePathContentProvider.class new file mode 100644 index 0000000..ddf1471 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ITreePathContentProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ITreePathLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/ITreePathLabelProvider.class new file mode 100644 index 0000000..333443f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ITreePathLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ITreeSelection.class b/Annotation/src/org/eclipse/jface/viewers/ITreeSelection.class new file mode 100644 index 0000000..8166df9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ITreeSelection.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ITreeViewerListener.class b/Annotation/src/org/eclipse/jface/viewers/ITreeViewerListener.class new file mode 100644 index 0000000..ba0a84b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ITreeViewerListener.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/IViewerLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/IViewerLabelProvider.class new file mode 100644 index 0000000..56c7167 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/IViewerLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/LabelDecorator.class b/Annotation/src/org/eclipse/jface/viewers/LabelDecorator.class new file mode 100644 index 0000000..1233fb2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/LabelDecorator.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/LabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/LabelProvider.class new file mode 100644 index 0000000..8fda3fc Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/LabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/LabelProviderChangedEvent.class b/Annotation/src/org/eclipse/jface/viewers/LabelProviderChangedEvent.class new file mode 100644 index 0000000..0d96c88 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/LabelProviderChangedEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ListViewer.class b/Annotation/src/org/eclipse/jface/viewers/ListViewer.class new file mode 100644 index 0000000..62ec486 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ListViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/NamedHandleObjectLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/NamedHandleObjectLabelProvider.class new file mode 100644 index 0000000..ffb6b41 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/NamedHandleObjectLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/OpenEvent.class b/Annotation/src/org/eclipse/jface/viewers/OpenEvent.class new file mode 100644 index 0000000..7c6b7bd Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/OpenEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider$1.class b/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider$1.class new file mode 100644 index 0000000..39569fd Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider$2.class b/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider$2.class new file mode 100644 index 0000000..88d3ee2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider$3.class b/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider$3.class new file mode 100644 index 0000000..21f765b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider.class new file mode 100644 index 0000000..aea2b46 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/OwnerDrawLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager$1.class b/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager$1.class new file mode 100644 index 0000000..599be83 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager$2.class b/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager$2.class new file mode 100644 index 0000000..9fb75e0 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager$3.class b/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager$3.class new file mode 100644 index 0000000..03606f8 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager.class b/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager.class new file mode 100644 index 0000000..57e6b57 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/SWTFocusCellManager.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/SelectionChangedEvent.class b/Annotation/src/org/eclipse/jface/viewers/SelectionChangedEvent.class new file mode 100644 index 0000000..6199b71 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/SelectionChangedEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredSelection.class b/Annotation/src/org/eclipse/jface/viewers/StructuredSelection.class new file mode 100644 index 0000000..27e23bb Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredSelection.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$1.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$1.class new file mode 100644 index 0000000..20bec0e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$2.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$2.class new file mode 100644 index 0000000..690ee96 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$3.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$3.class new file mode 100644 index 0000000..ea8ab53 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$4.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$4.class new file mode 100644 index 0000000..b56116b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$4.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$5.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$5.class new file mode 100644 index 0000000..9447435 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$5.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$6.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$6.class new file mode 100644 index 0000000..29904a6 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$6.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$7.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$7.class new file mode 100644 index 0000000..abf8c67 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$7.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$8.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$8.class new file mode 100644 index 0000000..661984c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$8.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$9.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$9.class new file mode 100644 index 0000000..b4d8314 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$9.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$ColorAndFontCollector.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$ColorAndFontCollector.class new file mode 100644 index 0000000..a4bddce Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$ColorAndFontCollector.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$ColorAndFontCollectorWithProviders.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$ColorAndFontCollectorWithProviders.class new file mode 100644 index 0000000..2e2cdbc Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$ColorAndFontCollectorWithProviders.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$UpdateItemSafeRunnable.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$UpdateItemSafeRunnable.class new file mode 100644 index 0000000..9d7005c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer$UpdateItemSafeRunnable.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/StructuredViewer.class b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer.class new file mode 100644 index 0000000..cbbb2a1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/StructuredViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableColumnViewerLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/TableColumnViewerLabelProvider.class new file mode 100644 index 0000000..e264c23 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableColumnViewerLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableLayout.class b/Annotation/src/org/eclipse/jface/viewers/TableLayout.class new file mode 100644 index 0000000..6d95dd1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableLayout.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$1.class b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$1.class new file mode 100644 index 0000000..0a6a9b6 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$2.class b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$2.class new file mode 100644 index 0000000..8dce620 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$3.class b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$3.class new file mode 100644 index 0000000..d7c5f8f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$4.class b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$4.class new file mode 100644 index 0000000..b0e276b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$4.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$TableTreeEditorImpl.class b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$TableTreeEditorImpl.class new file mode 100644 index 0000000..56967a4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer$TableTreeEditorImpl.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer.class b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer.class new file mode 100644 index 0000000..9399f88 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableTreeViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableViewer$1.class b/Annotation/src/org/eclipse/jface/viewers/TableViewer$1.class new file mode 100644 index 0000000..8bd1d1b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableViewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableViewer.class b/Annotation/src/org/eclipse/jface/viewers/TableViewer.class new file mode 100644 index 0000000..a083fcd Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableViewerColumn.class b/Annotation/src/org/eclipse/jface/viewers/TableViewerColumn.class new file mode 100644 index 0000000..ab9176e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableViewerColumn.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableViewerEditor.class b/Annotation/src/org/eclipse/jface/viewers/TableViewerEditor.class new file mode 100644 index 0000000..f192412 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableViewerEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableViewerFocusCellManager.class b/Annotation/src/org/eclipse/jface/viewers/TableViewerFocusCellManager.class new file mode 100644 index 0000000..42786fe Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableViewerFocusCellManager.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TableViewerRow.class b/Annotation/src/org/eclipse/jface/viewers/TableViewerRow.class new file mode 100644 index 0000000..92fa6f2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TableViewerRow.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$1.class b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$1.class new file mode 100644 index 0000000..efe4f7e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$2.class b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$2.class new file mode 100644 index 0000000..6aa9b2a Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$3.class b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$3.class new file mode 100644 index 0000000..9b098e2 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$4.class b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$4.class new file mode 100644 index 0000000..29aede9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$4.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$5.class b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$5.class new file mode 100644 index 0000000..5c97f1e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$5.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$6.class b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$6.class new file mode 100644 index 0000000..fa803d9 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor$6.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TextCellEditor.class b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor.class new file mode 100644 index 0000000..9782e3f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TextCellEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeColumnViewerLabelProvider$1.class b/Annotation/src/org/eclipse/jface/viewers/TreeColumnViewerLabelProvider$1.class new file mode 100644 index 0000000..d5a7ccf Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeColumnViewerLabelProvider$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeColumnViewerLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/TreeColumnViewerLabelProvider.class new file mode 100644 index 0000000..5de7cba Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeColumnViewerLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeExpansionEvent.class b/Annotation/src/org/eclipse/jface/viewers/TreeExpansionEvent.class new file mode 100644 index 0000000..c68ec65 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeExpansionEvent.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeNode.class b/Annotation/src/org/eclipse/jface/viewers/TreeNode.class new file mode 100644 index 0000000..fc9a6fb Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeNode.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeNodeContentProvider.class b/Annotation/src/org/eclipse/jface/viewers/TreeNodeContentProvider.class new file mode 100644 index 0000000..71d2d6d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeNodeContentProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreePath.class b/Annotation/src/org/eclipse/jface/viewers/TreePath.class new file mode 100644 index 0000000..a8f81e4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreePath.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreePathViewerSorter$1.class b/Annotation/src/org/eclipse/jface/viewers/TreePathViewerSorter$1.class new file mode 100644 index 0000000..c7c665b Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreePathViewerSorter$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreePathViewerSorter.class b/Annotation/src/org/eclipse/jface/viewers/TreePathViewerSorter.class new file mode 100644 index 0000000..ed98fad Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreePathViewerSorter.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeSelection$InitializeData.class b/Annotation/src/org/eclipse/jface/viewers/TreeSelection$InitializeData.class new file mode 100644 index 0000000..8b04580 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeSelection$InitializeData.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeSelection.class b/Annotation/src/org/eclipse/jface/viewers/TreeSelection.class new file mode 100644 index 0000000..b5974b0 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeSelection.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewer$1.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$1.class new file mode 100644 index 0000000..17378db Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewer$2.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$2.class new file mode 100644 index 0000000..cb41936 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewer$3.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$3.class new file mode 100644 index 0000000..ce23450 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$3.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewer$4.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$4.class new file mode 100644 index 0000000..acfde98 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$4.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewer$5.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$5.class new file mode 100644 index 0000000..2cd1145 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$5.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewer$6.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$6.class new file mode 100644 index 0000000..1464361 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewer$6.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewer.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewer.class new file mode 100644 index 0000000..60fde98 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewerColumn.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewerColumn.class new file mode 100644 index 0000000..b825275 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewerColumn.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewerEditor.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewerEditor.class new file mode 100644 index 0000000..5a36135 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewerEditor.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewerFocusCellManager$1.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewerFocusCellManager$1.class new file mode 100644 index 0000000..3cf6d9d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewerFocusCellManager$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewerFocusCellManager.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewerFocusCellManager.class new file mode 100644 index 0000000..909b446 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewerFocusCellManager.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/TreeViewerRow.class b/Annotation/src/org/eclipse/jface/viewers/TreeViewerRow.class new file mode 100644 index 0000000..90c756e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/TreeViewerRow.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/Viewer$1.class b/Annotation/src/org/eclipse/jface/viewers/Viewer$1.class new file mode 100644 index 0000000..1c1c323 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/Viewer$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/Viewer$2.class b/Annotation/src/org/eclipse/jface/viewers/Viewer$2.class new file mode 100644 index 0000000..17ed7af Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/Viewer$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/Viewer.class b/Annotation/src/org/eclipse/jface/viewers/Viewer.class new file mode 100644 index 0000000..01b492d Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/Viewer.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ViewerCell.class b/Annotation/src/org/eclipse/jface/viewers/ViewerCell.class new file mode 100644 index 0000000..46eda71 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ViewerCell.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ViewerColumn$1.class b/Annotation/src/org/eclipse/jface/viewers/ViewerColumn$1.class new file mode 100644 index 0000000..57655af Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ViewerColumn$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ViewerColumn$2.class b/Annotation/src/org/eclipse/jface/viewers/ViewerColumn$2.class new file mode 100644 index 0000000..a973e99 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ViewerColumn$2.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ViewerColumn.class b/Annotation/src/org/eclipse/jface/viewers/ViewerColumn.class new file mode 100644 index 0000000..783f4cc Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ViewerColumn.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ViewerComparator$1.class b/Annotation/src/org/eclipse/jface/viewers/ViewerComparator$1.class new file mode 100644 index 0000000..ba86701 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ViewerComparator$1.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ViewerComparator.class b/Annotation/src/org/eclipse/jface/viewers/ViewerComparator.class new file mode 100644 index 0000000..93cd551 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ViewerComparator.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ViewerDropAdapter.class b/Annotation/src/org/eclipse/jface/viewers/ViewerDropAdapter.class new file mode 100644 index 0000000..93de622 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ViewerDropAdapter.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ViewerFilter.class b/Annotation/src/org/eclipse/jface/viewers/ViewerFilter.class new file mode 100644 index 0000000..3ecc080 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ViewerFilter.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ViewerLabel.class b/Annotation/src/org/eclipse/jface/viewers/ViewerLabel.class new file mode 100644 index 0000000..4d104a4 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ViewerLabel.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ViewerRow.class b/Annotation/src/org/eclipse/jface/viewers/ViewerRow.class new file mode 100644 index 0000000..b56558e Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ViewerRow.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/ViewerSorter.class b/Annotation/src/org/eclipse/jface/viewers/ViewerSorter.class new file mode 100644 index 0000000..39b774c Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/ViewerSorter.class differ diff --git a/Annotation/src/org/eclipse/jface/viewers/WrappedViewerLabelProvider.class b/Annotation/src/org/eclipse/jface/viewers/WrappedViewerLabelProvider.class new file mode 100644 index 0000000..cf72d46 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/viewers/WrappedViewerLabelProvider.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/IWizard.class b/Annotation/src/org/eclipse/jface/wizard/IWizard.class new file mode 100644 index 0000000..446a6b5 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/IWizard.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/IWizardContainer.class b/Annotation/src/org/eclipse/jface/wizard/IWizardContainer.class new file mode 100644 index 0000000..46049c5 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/IWizardContainer.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/IWizardContainer2.class b/Annotation/src/org/eclipse/jface/wizard/IWizardContainer2.class new file mode 100644 index 0000000..bcd0e2f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/IWizardContainer2.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/IWizardNode.class b/Annotation/src/org/eclipse/jface/wizard/IWizardNode.class new file mode 100644 index 0000000..71d71f0 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/IWizardNode.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/IWizardPage.class b/Annotation/src/org/eclipse/jface/wizard/IWizardPage.class new file mode 100644 index 0000000..62fc556 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/IWizardPage.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/ProgressMonitorPart$1.class b/Annotation/src/org/eclipse/jface/wizard/ProgressMonitorPart$1.class new file mode 100644 index 0000000..730e407 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/ProgressMonitorPart$1.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/ProgressMonitorPart.class b/Annotation/src/org/eclipse/jface/wizard/ProgressMonitorPart.class new file mode 100644 index 0000000..898676f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/ProgressMonitorPart.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/Wizard.class b/Annotation/src/org/eclipse/jface/wizard/Wizard.class new file mode 100644 index 0000000..c780b8f Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/Wizard.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/WizardDialog$1.class b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$1.class new file mode 100644 index 0000000..5c1ac53 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$1.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/WizardDialog$2.class b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$2.class new file mode 100644 index 0000000..9779854 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$2.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/WizardDialog$3.class b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$3.class new file mode 100644 index 0000000..da1aec3 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$3.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/WizardDialog$4.class b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$4.class new file mode 100644 index 0000000..28a5e25 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$4.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/WizardDialog$5.class b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$5.class new file mode 100644 index 0000000..af899f1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$5.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/WizardDialog$6.class b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$6.class new file mode 100644 index 0000000..31d44d1 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$6.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/WizardDialog$PageContainerFillLayout.class b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$PageContainerFillLayout.class new file mode 100644 index 0000000..7cc9a15 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/WizardDialog$PageContainerFillLayout.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/WizardDialog.class b/Annotation/src/org/eclipse/jface/wizard/WizardDialog.class new file mode 100644 index 0000000..00fb6c5 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/WizardDialog.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/WizardPage.class b/Annotation/src/org/eclipse/jface/wizard/WizardPage.class new file mode 100644 index 0000000..90e1f62 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/WizardPage.class differ diff --git a/Annotation/src/org/eclipse/jface/wizard/WizardSelectionPage.class b/Annotation/src/org/eclipse/jface/wizard/WizardSelectionPage.class new file mode 100644 index 0000000..2343e25 Binary files /dev/null and b/Annotation/src/org/eclipse/jface/wizard/WizardSelectionPage.class differ diff --git a/Annotation/src/org/eclipse/swt/SWT.class b/Annotation/src/org/eclipse/swt/SWT.class new file mode 100644 index 0000000..3c3c03b Binary files /dev/null and b/Annotation/src/org/eclipse/swt/SWT.class differ diff --git a/Annotation/src/org/eclipse/swt/SWTError.class b/Annotation/src/org/eclipse/swt/SWTError.class new file mode 100644 index 0000000..81a665a Binary files /dev/null and b/Annotation/src/org/eclipse/swt/SWTError.class differ diff --git a/Annotation/src/org/eclipse/swt/SWTException.class b/Annotation/src/org/eclipse/swt/SWTException.class new file mode 100644 index 0000000..99b2dd7 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/SWTException.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/XPCOM.class b/Annotation/src/org/eclipse/swt/internal/mozilla/XPCOM.class new file mode 100644 index 0000000..56e9b95 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/XPCOM.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/XPCOMObject.class b/Annotation/src/org/eclipse/swt/internal/mozilla/XPCOMObject.class new file mode 100644 index 0000000..29fb7fb Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/XPCOMObject.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsDynamicFunctionLoad.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsDynamicFunctionLoad.class new file mode 100644 index 0000000..d802b8f Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsDynamicFunctionLoad.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsEmbedString.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsEmbedString.class new file mode 100644 index 0000000..700b7fe Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsEmbedString.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIAppShell.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIAppShell.class new file mode 100644 index 0000000..4ac00e4 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIAppShell.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIAuthInformation.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIAuthInformation.class new file mode 100644 index 0000000..6db6f58 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIAuthInformation.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIBaseWindow.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIBaseWindow.class new file mode 100644 index 0000000..04588ef Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIBaseWindow.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsICancelable.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICancelable.class new file mode 100644 index 0000000..e3b7714 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICancelable.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsICategoryManager.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICategoryManager.class new file mode 100644 index 0000000..db4860c Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICategoryManager.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIChannel.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIChannel.class new file mode 100644 index 0000000..e9d5b2a Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIChannel.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIClassInfo.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIClassInfo.class new file mode 100644 index 0000000..347b939 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIClassInfo.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIComponentManager.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIComponentManager.class new file mode 100644 index 0000000..7395c5d Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIComponentManager.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIComponentRegistrar.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIComponentRegistrar.class new file mode 100644 index 0000000..f0239c1 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIComponentRegistrar.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIContextMenuListener.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIContextMenuListener.class new file mode 100644 index 0000000..b28ebd0 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIContextMenuListener.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookie.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookie.class new file mode 100644 index 0000000..e9ba855 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookie.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookieManager.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookieManager.class new file mode 100644 index 0000000..ebec6f9 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookieManager.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookieService.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookieService.class new file mode 100644 index 0000000..eeb6335 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookieService.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookieService_1_9.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookieService_1_9.class new file mode 100644 index 0000000..14234a1 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsICookieService_1_9.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsID.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsID.class new file mode 100644 index 0000000..1b241db Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsID.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMEvent.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMEvent.class new file mode 100644 index 0000000..c55de24 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMEvent.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMEventTarget.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMEventTarget.class new file mode 100644 index 0000000..317f0ea Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMEventTarget.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMKeyEvent.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMKeyEvent.class new file mode 100644 index 0000000..1e5eeb2 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMKeyEvent.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMMouseEvent.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMMouseEvent.class new file mode 100644 index 0000000..8113e96 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMMouseEvent.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMSerializer.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMSerializer.class new file mode 100644 index 0000000..c86a914 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMSerializer.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMSerializer_1_7.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMSerializer_1_7.class new file mode 100644 index 0000000..16658b8 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMSerializer_1_7.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMUIEvent.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMUIEvent.class new file mode 100644 index 0000000..f42af3a Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMUIEvent.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMWindow.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMWindow.class new file mode 100644 index 0000000..016a4a5 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMWindow.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMWindowCollection.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMWindowCollection.class new file mode 100644 index 0000000..23e73da Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDOMWindowCollection.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDataType.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDataType.class new file mode 100644 index 0000000..dfea513 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDataType.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDirectoryService.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDirectoryService.class new file mode 100644 index 0000000..62c77b3 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDirectoryService.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDirectoryServiceProvider.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDirectoryServiceProvider.class new file mode 100644 index 0000000..6aa81ad Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDirectoryServiceProvider.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDirectoryServiceProvider2.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDirectoryServiceProvider2.class new file mode 100644 index 0000000..20f5018 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDirectoryServiceProvider2.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDocShell.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDocShell.class new file mode 100644 index 0000000..7d34822 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDocShell.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDocShell_1_8.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDocShell_1_8.class new file mode 100644 index 0000000..9275514 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDocShell_1_8.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDownload.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDownload.class new file mode 100644 index 0000000..243014b Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDownload.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDownload_1_8.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDownload_1_8.class new file mode 100644 index 0000000..bbfd321 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIDownload_1_8.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIEmbeddingSiteWindow.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIEmbeddingSiteWindow.class new file mode 100644 index 0000000..d6e03c3 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIEmbeddingSiteWindow.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFactory.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFactory.class new file mode 100644 index 0000000..b23809a Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFactory.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFile.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFile.class new file mode 100644 index 0000000..a56fb64 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFile.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFilePicker.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFilePicker.class new file mode 100644 index 0000000..438c84c Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFilePicker.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFilePicker_1_8.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFilePicker_1_8.class new file mode 100644 index 0000000..d44c1f6 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIFilePicker_1_8.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher.class new file mode 100644 index 0000000..57cd4fd Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncherDialog.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncherDialog.class new file mode 100644 index 0000000..66abeea Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncherDialog.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncherDialog_1_9.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncherDialog_1_9.class new file mode 100644 index 0000000..8298882 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncherDialog_1_9.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher_1_8.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher_1_8.class new file mode 100644 index 0000000..ab75d99 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher_1_8.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher_1_9.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher_1_9.class new file mode 100644 index 0000000..7bad12f Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher_1_9.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIIOService.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIIOService.class new file mode 100644 index 0000000..21f2103 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIIOService.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIInputStream.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIInputStream.class new file mode 100644 index 0000000..8af96b0 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIInputStream.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIInterfaceRequestor.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIInterfaceRequestor.class new file mode 100644 index 0000000..e7ead38 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIInterfaceRequestor.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIJSContextStack.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIJSContextStack.class new file mode 100644 index 0000000..58e3a67 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIJSContextStack.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsILocalFile.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsILocalFile.class new file mode 100644 index 0000000..3ee4642 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsILocalFile.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIMemory.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIMemory.class new file mode 100644 index 0000000..d30f3b8 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIMemory.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIObserverService.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIObserverService.class new file mode 100644 index 0000000..9f48c64 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIObserverService.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrefBranch.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrefBranch.class new file mode 100644 index 0000000..05ae8bb Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrefBranch.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrefLocalizedString.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrefLocalizedString.class new file mode 100644 index 0000000..db3a8ce Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrefLocalizedString.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrefService.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrefService.class new file mode 100644 index 0000000..23c6f81 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrefService.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrincipal.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrincipal.class new file mode 100644 index 0000000..e10b9a2 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPrincipal.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIProgressDialog.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIProgressDialog.class new file mode 100644 index 0000000..c646543 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIProgressDialog.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIProgressDialog_1_8.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIProgressDialog_1_8.class new file mode 100644 index 0000000..d3ee6b5 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIProgressDialog_1_8.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPromptService.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPromptService.class new file mode 100644 index 0000000..983a740 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPromptService.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPromptService2.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPromptService2.class new file mode 100644 index 0000000..c8213df Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIPromptService2.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIProperties.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIProperties.class new file mode 100644 index 0000000..08aeee5 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIProperties.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIRequest.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIRequest.class new file mode 100644 index 0000000..1e10d89 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIRequest.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIScriptSecurityManager_1_9.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIScriptSecurityManager_1_9.class new file mode 100644 index 0000000..8bd8ea6 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIScriptSecurityManager_1_9.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIScriptSecurityManager_1_9_1.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIScriptSecurityManager_1_9_1.class new file mode 100644 index 0000000..a3ed690 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIScriptSecurityManager_1_9_1.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsISecurityCheckedComponent.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsISecurityCheckedComponent.class new file mode 100644 index 0000000..759a76b Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsISecurityCheckedComponent.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsISerializable.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsISerializable.class new file mode 100644 index 0000000..13b3037 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsISerializable.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIServiceManager.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIServiceManager.class new file mode 100644 index 0000000..1bf9c91 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIServiceManager.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsISimpleEnumerator.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsISimpleEnumerator.class new file mode 100644 index 0000000..12ee7fe Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsISimpleEnumerator.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsISupports.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsISupports.class new file mode 100644 index 0000000..6f70471 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsISupports.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsISupportsWeakReference.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsISupportsWeakReference.class new file mode 100644 index 0000000..eef3fe0 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsISupportsWeakReference.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsITooltipListener.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsITooltipListener.class new file mode 100644 index 0000000..b0843a4 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsITooltipListener.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsITransfer.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsITransfer.class new file mode 100644 index 0000000..ae12b7e Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsITransfer.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIURI.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIURI.class new file mode 100644 index 0000000..3e0d315 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIURI.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIURIContentListener.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIURIContentListener.class new file mode 100644 index 0000000..0a82d6b Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIURIContentListener.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIVariant.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIVariant.class new file mode 100644 index 0000000..9ae5b3c Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIVariant.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWeakReference.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWeakReference.class new file mode 100644 index 0000000..a474c58 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWeakReference.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowser.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowser.class new file mode 100644 index 0000000..6403628 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowser.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserChrome.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserChrome.class new file mode 100644 index 0000000..a77dbd4 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserChrome.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserChromeFocus.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserChromeFocus.class new file mode 100644 index 0000000..3e96160 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserChromeFocus.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserFocus.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserFocus.class new file mode 100644 index 0000000..e0d5bf2 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserFocus.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserSetup.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserSetup.class new file mode 100644 index 0000000..9222514 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserSetup.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserStream.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserStream.class new file mode 100644 index 0000000..f7a2412 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserStream.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebNavigation.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebNavigation.class new file mode 100644 index 0000000..6a2e287 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebNavigation.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebNavigationInfo.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebNavigationInfo.class new file mode 100644 index 0000000..d3f1acf Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebNavigationInfo.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebProgress.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebProgress.class new file mode 100644 index 0000000..974dfe2 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebProgress.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebProgressListener.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebProgressListener.class new file mode 100644 index 0000000..41a1195 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebProgressListener.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebProgressListener2.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebProgressListener2.class new file mode 100644 index 0000000..b4fcddd Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWebProgressListener2.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWindowCreator.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWindowCreator.class new file mode 100644 index 0000000..a4fa617 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWindowCreator.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWindowCreator2.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWindowCreator2.class new file mode 100644 index 0000000..138990d Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWindowCreator2.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWindowWatcher.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWindowWatcher.class new file mode 100644 index 0000000..a44914d Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWindowWatcher.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWritableVariant.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWritableVariant.class new file mode 100644 index 0000000..cfe3ee5 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIWritableVariant.class differ diff --git a/Annotation/src/org/eclipse/swt/internal/mozilla/nsIXPCSecurityManager.class b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIXPCSecurityManager.class new file mode 100644 index 0000000..5aa5b58 Binary files /dev/null and b/Annotation/src/org/eclipse/swt/internal/mozilla/nsIXPCSecurityManager.class differ diff --git a/Annotation/version.txt b/Annotation/version.txt new file mode 100644 index 0000000..d6761c7 --- /dev/null +++ b/Annotation/version.txt @@ -0,0 +1 @@ +version 3.550 \ No newline at end of file