Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwbeaton2005-11-30 04:39:30 +0000
committerwbeaton2005-11-30 04:39:30 +0000
commitbf2548c2801ad91cbeba7160346b66ed8e6637fc (patch)
tree0447bffc1d63bb2c0cda5bb97c075da8725a120b
parentd7f19153edf2189dfbb204c3a58f4d2081dcb9db (diff)
downloadarticles-bf2548c2801ad91cbeba7160346b66ed8e6637fc.tar.gz
articles-bf2548c2801ad91cbeba7160346b66ed8e6637fc.tar.xz
articles-bf2548c2801ad91cbeba7160346b66ed8e6637fc.zip
Added the rest of the existing articles.
-rw-r--r--Article-EditorContributor/EditorContributor.html235
-rw-r--r--Article-EditorContributor/images/Adarrow.gifbin0 -> 857 bytes
-rw-r--r--Article-EditorContributor/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-EditorContributor/images/articles.gifbin0 -> 2012 bytes
-rw-r--r--Article-EditorContributor/images/howto_banner.jpgbin0 -> 9877 bytes
-rw-r--r--Article-EditorContributor/images/htmltoolbar.jpgbin0 -> 39205 bytes
-rw-r--r--Article-EditorContributor/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-EditorContributor/images/markers.jpgbin0 -> 190691 bytes
-rw-r--r--Article-EditorContributor/images/normaltoolbar.jpgbin0 -> 24853 bytes
-rw-r--r--Article-EditorContributor/images/note.gifbin0 -> 1014 bytes
-rw-r--r--Article-EditorContributor/images/notifiers.gifbin0 -> 7404 bytes
-rw-r--r--Article-EditorContributor/images/srctoolbar.jpgbin0 -> 38142 bytes
-rw-r--r--Article-EditorContributor/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-EditorContributor/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-EditorContributor/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-EditorContributor/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-EditorContributor/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-EditorContributor/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-EditorContributor/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-EditorContributor/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-EditorContributor/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-EditorContributor/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-EditorContributor/images/write.pngbin0 -> 1982 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/default_style.css11
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/folding.html395
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/Thumbs.dbbin0 -> 77312 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/annotationSummary.pngbin0 -> 6781 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/hover.pngbin0 -> 3761 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/note.gifbin0 -> 1014 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/projectionAnnotation.pngbin0 -> 5421 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/withFolding.pngbin0 -> 6893 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/withoutFolding.pngbin0 -> 4266 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/xmlEditor.pngbin0 -> 9712 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/images/xmlEditor1.gifbin0 -> 18496 bytes
-rw-r--r--Article-Folding-in-Eclipse-Text-Editors/xmlEditorPlugin.zipbin0 -> 36521 bytes
-rw-r--r--Article-GEF-Draw2d/GEF-Draw2d.html379
-rw-r--r--Article-GEF-Draw2d/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-GEF-Draw2d/images/UMLDiagGIF.gifbin0 -> 6806 bytes
-rw-r--r--Article-GEF-Draw2d/images/classDiagConnectionGIF.gifbin0 -> 7191 bytes
-rw-r--r--Article-GEF-Draw2d/images/classDiagDecoGIF.gifbin0 -> 7081 bytes
-rw-r--r--Article-GEF-Draw2d/images/classDiagGIF.gifbin0 -> 1359 bytes
-rw-r--r--Article-GEF-Draw2d/images/classDiagLabelsGIF.gifbin0 -> 7274 bytes
-rw-r--r--Article-GEF-Draw2d/images/class_obj.gifbin0 -> 194 bytes
-rw-r--r--Article-GEF-Draw2d/images/field_private_obj.gifbin0 -> 109 bytes
-rw-r--r--Article-GEF-Draw2d/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-GEF-Draw2d/images/methpub_obj.gifbin0 -> 121 bytes
-rw-r--r--Article-GEF-Draw2d/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-GEF-Draw2d/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-GEF-Draw2d/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-GEF-Draw2d/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-GEF-Draw2d/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-GEF-Draw2d/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-GEF-Draw2d/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-GEF-Draw2d/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-GEF-Draw2d/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-GEF-Draw2d/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-GEF-EMF/article_style.css25
-rw-r--r--Article-GEF-EMF/files/shapesemf.zipbin0 -> 124972 bytes
-rw-r--r--Article-GEF-EMF/files/shapesmerlin.zipbin0 -> 126914 bytes
-rw-r--r--Article-GEF-EMF/files/shapesrcp.zipbin0 -> 83666 bytes
-rw-r--r--Article-GEF-EMF/gef-emf.html758
-rw-r--r--Article-GEF-EMF/images/connection.pngbin0 -> 6399 bytes
-rw-r--r--Article-GEF-EMF/images/ediagram.jpgbin0 -> 76959 bytes
-rw-r--r--Article-GEF-EMF/images/shape.pngbin0 -> 5108 bytes
-rw-r--r--Article-GEF-EMF/images/shapesdiagram.pngbin0 -> 4215 bytes
-rw-r--r--Article-GEF-EMF/images/shapesmerlin.pngbin0 -> 47038 bytes
-rw-r--r--Article-GEF-EMF/images/shapesmodel.pngbin0 -> 23852 bytes
-rw-r--r--Article-GEF-EMF/images/shapesrcp.pngbin0 -> 29524 bytes
-rw-r--r--Article-GEF-EMF/images/shapetypes.pngbin0 -> 4808 bytes
-rw-r--r--Article-GEF-diagram-editor/default_style.css49
-rw-r--r--Article-GEF-diagram-editor/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-GEF-diagram-editor/images/delete_action3.gifbin0 -> 11173 bytes
-rw-r--r--Article-GEF-diagram-editor/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-GEF-diagram-editor/images/shape_screenshot2.jpgbin0 -> 61063 bytes
-rw-r--r--Article-GEF-diagram-editor/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-GEF-diagram-editor/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-GEF-diagram-editor/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-GEF-diagram-editor/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-GEF-diagram-editor/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-GEF-diagram-editor/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-GEF-diagram-editor/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-GEF-diagram-editor/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-GEF-diagram-editor/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-GEF-diagram-editor/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-GEF-diagram-editor/shape.html1289
-rw-r--r--Article-GEF-dnd/DNDExample.java57
-rw-r--r--Article-GEF-dnd/GEF-dnd.html321
-rw-r--r--Article-GEF-editor/gef-schema-editor.html1000
-rw-r--r--Article-GEF-editor/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-GEF-editor/images/editor.JPGbin0 -> 72480 bytes
-rw-r--r--Article-GEF-editor/images/layout.gifbin0 -> 866 bytes
-rw-r--r--Article-GEF-editor/images/revalidate-s.JPGbin0 -> 18872 bytes
-rw-r--r--Article-GEF-editor/images/revalidate.JPGbin0 -> 63161 bytes
-rw-r--r--Article-GEF-editor/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-GEF-editor/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-GEF-editor/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-GEF-editor/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-GEF-editor/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-GEF-editor/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-GEF-editor/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-GEF-editor/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-GEF-editor/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-GEF-editor/schemaeditor.zipbin0 -> 172647 bytes
-rw-r--r--Article-Image-Viewer/Image_viewer.html831
-rw-r--r--Article-Image-Viewer/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Image-Viewer/images/activity.bmpbin0 -> 241436 bytes
-rw-r--r--Article-Image-Viewer/images/allClass.jpgbin0 -> 105528 bytes
-rw-r--r--Article-Image-Viewer/images/all_classes.jpgbin0 -> 105528 bytes
-rw-r--r--Article-Image-Viewer/images/buttons.bmpbin0 -> 9206 bytes
-rw-r--r--Article-Image-Viewer/images/buttons.jpgbin0 -> 12660 bytes
-rw-r--r--Article-Image-Viewer/images/flower.jpgbin0 -> 260619 bytes
-rw-r--r--Article-Image-Viewer/images/gap.bmpbin0 -> 53368 bytes
-rw-r--r--Article-Image-Viewer/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-Image-Viewer/images/model.bmpbin0 -> 838424 bytes
-rw-r--r--Article-Image-Viewer/images/note.gifbin0 -> 260 bytes
-rw-r--r--Article-Image-Viewer/images/open.bmpbin0 -> 332456 bytes
-rw-r--r--Article-Image-Viewer/images/open1.bmpbin0 -> 396564 bytes
-rw-r--r--Article-Image-Viewer/images/open_activity.jpgbin0 -> 47605 bytes
-rw-r--r--Article-Image-Viewer/images/paint.bmpbin0 -> 424742 bytes
-rw-r--r--Article-Image-Viewer/images/render_flowchart.jpgbin0 -> 42340 bytes
-rw-r--r--Article-Image-Viewer/images/render_model.jpgbin0 -> 136577 bytes
-rw-r--r--Article-Image-Viewer/images/screen_shot.jpgbin0 -> 66441 bytes
-rw-r--r--Article-Image-Viewer/images/scroll_zoom_activity.jpgbin0 -> 47790 bytes
-rw-r--r--Article-Image-Viewer/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Image-Viewer/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Image-Viewer/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Image-Viewer/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Image-Viewer/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Image-Viewer/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Image-Viewer/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Image-Viewer/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Image-Viewer/images/transform.bmpbin0 -> 145056 bytes
-rw-r--r--Article-Image-Viewer/images/transform.jpgbin0 -> 25281 bytes
-rw-r--r--Article-Image-Viewer/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Image-Viewer/images/viewer.jpgbin0 -> 66441 bytes
-rw-r--r--Article-Image-Viewer/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-Image-Viewer/imageviewer.zipbin0 -> 34037 bytes
-rw-r--r--Article-Internationalization/how2I18n.html1255
-rw-r--r--Article-Internationalization/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Internationalization/images/envelope.jpgbin0 -> 999 bytes
-rw-r--r--Article-Internationalization/images/fraggen1.jpgbin0 -> 27285 bytes
-rw-r--r--Article-Internationalization/images/fraggen2.jpgbin0 -> 25323 bytes
-rw-r--r--Article-Internationalization/images/fraggen3.jpgbin0 -> 27675 bytes
-rw-r--r--Article-Internationalization/images/image2.jpgbin0 -> 42281 bytes
-rw-r--r--Article-Internationalization/images/image20.jpgbin0 -> 35533 bytes
-rw-r--r--Article-Internationalization/images/image23.jpgbin0 -> 30548 bytes
-rw-r--r--Article-Internationalization/images/image24.jpgbin0 -> 62704 bytes
-rw-r--r--Article-Internationalization/images/image25.jpgbin0 -> 29541 bytes
-rw-r--r--Article-Internationalization/images/image26.jpgbin0 -> 43230 bytes
-rw-r--r--Article-Internationalization/images/image28.jpgbin0 -> 15963 bytes
-rw-r--r--Article-Internationalization/images/image6.jpgbin0 -> 44859 bytes
-rw-r--r--Article-Internationalization/images/image7.jpgbin0 -> 37554 bytes
-rw-r--r--Article-Internationalization/images/image8.jpgbin0 -> 26117 bytes
-rw-r--r--Article-Internationalization/images/image9.jpgbin0 -> 57819 bytes
-rw-r--r--Article-Internationalization/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-Internationalization/images/mailbox.jpgbin0 -> 3692 bytes
-rw-r--r--Article-Internationalization/images/nav3.jpgbin0 -> 22540 bytes
-rw-r--r--Article-Internationalization/images/never.jpgbin0 -> 787 bytes
-rw-r--r--Article-Internationalization/images/route66.jpgbin0 -> 1895 bytes
-rw-r--r--Article-Internationalization/images/skip.jpgbin0 -> 781 bytes
-rw-r--r--Article-Internationalization/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Internationalization/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Internationalization/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Internationalization/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Internationalization/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Internationalization/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Internationalization/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Internationalization/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Internationalization/images/translate.jpgbin0 -> 753 bytes
-rw-r--r--Article-Internationalization/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Internationalization/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-JET/default_style.css24
-rw-r--r--Article-JET/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-JET/images/addJetNaturePopup.gifbin0 -> 4234 bytes
-rw-r--r--Article-JET/images/compiledTemplate.gifbin0 -> 3686 bytes
-rw-r--r--Article-JET/images/generator_skeleton.gifbin0 -> 6127 bytes
-rw-r--r--Article-JET/images/jetWizard.gifbin0 -> 12761 bytes
-rw-r--r--Article-JET/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-JET/images/missing_jet_directive.gifbin0 -> 6048 bytes
-rw-r--r--Article-JET/images/newproject.gifbin0 -> 2533 bytes
-rw-r--r--Article-JET/images/projectProperties.gifbin0 -> 8401 bytes
-rw-r--r--Article-JET/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-JET/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-JET/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-JET/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-JET/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-JET/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-JET/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-JET/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-JET/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-JET/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-JET/jet_tutorial1.html644
-rw-r--r--Article-JET/jet_tutorial1.html_old574
-rw-r--r--Article-JET/untitled.htm11
-rw-r--r--Article-JET2/JETCTask.java155
-rw-r--r--Article-JET2/default_style.css22
-rw-r--r--Article-JET2/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-JET2/images/enum_gui_page1.gifbin0 -> 9502 bytes
-rw-r--r--Article-JET2/images/enum_gui_page2.gifbin0 -> 11229 bytes
-rw-r--r--Article-JET2/images/enum_gui_page3.gifbin0 -> 13076 bytes
-rw-r--r--Article-JET2/images/jetemitter.gifbin0 -> 3439 bytes
-rw-r--r--Article-JET2/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-JET2/images/new_creation_wizard.gifbin0 -> 10466 bytes
-rw-r--r--Article-JET2/images/new_toolbar.gifbin0 -> 2030 bytes
-rw-r--r--Article-JET2/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-JET2/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-JET2/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-JET2/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-JET2/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-JET2/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-JET2/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-JET2/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-JET2/images/translate_action.gifbin0 -> 6703 bytes
-rw-r--r--Article-JET2/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-JET2/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-JET2/jet_tutorial2.html1033
-rw-r--r--Article-JET2/jet_tutorial2.html_old979
-rw-r--r--Article-JET2/jetc-task.jarbin0 -> 3823 bytes
-rw-r--r--Article-JET2/jp.azzurri.jet.article2.typesafe_enum_1.0.0.zipbin0 -> 93213 bytes
-rw-r--r--Article-JET2/org.eclipse.emf.examples.jet.article2_2.0.0.zipbin0 -> 88206 bytes
-rw-r--r--Article-JFace Wizards/wizardArticle.html484
-rw-r--r--Article-JFace Wizards/wizardsPlugin.jarbin0 -> 26922 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/car.gifbin0 -> 10787 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/error.gifbin0 -> 12420 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/mainPage.gifbin0 -> 12028 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/newWizard.gifbin0 -> 25239 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/plane.gifbin0 -> 11621 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/popup.gifbin0 -> 57598 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-JFace Wizards/wizards_files/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-Java-launch/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Java-launch/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-Java-launch/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Java-launch/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Java-launch/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Java-launch/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Java-launch/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Java-launch/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Java-launch/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Java-launch/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Java-launch/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Java-launch/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-Java-launch/launching-java.html444
-rw-r--r--Article-Java-launch/org.eclipse.jdt.launching.examples.tomcat.zipbin0 -> 16961 bytes
-rw-r--r--Article-Launch-Framework/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Launch-Framework/images/Screenshot1.gifbin0 -> 31894 bytes
-rw-r--r--Article-Launch-Framework/images/Screenshot2.gifbin0 -> 31575 bytes
-rw-r--r--Article-Launch-Framework/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Launch-Framework/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Launch-Framework/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Launch-Framework/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Launch-Framework/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Launch-Framework/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Launch-Framework/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Launch-Framework/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Launch-Framework/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Launch-Framework/launch.html1151
-rw-r--r--Article-Levels-Of-Integration/Levels Of Integration.html251
-rw-r--r--Article-Levels-Of-Integration/images/idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Mark My Words/Mark My Words.html375
-rw-r--r--Article-Mark My Words/images/bkmrk_tsk.gifbin0 -> 104 bytes
-rw-r--r--Article-Mark My Words/images/error_tsk.gifbin0 -> 903 bytes
-rw-r--r--Article-Mark My Words/images/idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Mark My Words/images/info_tsk.gifbin0 -> 94 bytes
-rw-r--r--Article-Mark My Words/images/markers.jpgbin0 -> 128954 bytes
-rw-r--r--Article-Mark My Words/images/task_tsk.gifbin0 -> 170 bytes
-rw-r--r--Article-Mark My Words/images/warn_tsk.gifbin0 -> 146 bytes
-rw-r--r--Article-Monitor/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Monitor/images/classDiagramDetail.gifbin0 -> 4504 bytes
-rw-r--r--Article-Monitor/images/classDiagramMain.gifbin0 -> 3565 bytes
-rw-r--r--Article-Monitor/images/logView.jpgbin0 -> 43111 bytes
-rw-r--r--Article-Monitor/images/monitoring.gifbin0 -> 2966 bytes
-rw-r--r--Article-Monitor/images/newServerWizard.gifbin0 -> 10946 bytes
-rw-r--r--Article-Monitor/images/preferences.gifbin0 -> 16925 bytes
-rw-r--r--Article-Monitor/images/sample1.gifbin0 -> 1358550 bytes
-rw-r--r--Article-Monitor/images/sample1.jpgbin0 -> 72435 bytes
-rw-r--r--Article-Monitor/images/serverOperations.jpgbin0 -> 88178 bytes
-rw-r--r--Article-Monitor/images/servers.gifbin0 -> 5957 bytes
-rw-r--r--Article-Monitor/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Monitor/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Monitor/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Monitor/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Monitor/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Monitor/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Monitor/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Monitor/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Monitor/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Monitor/monitorArticle.html430
-rw-r--r--Article-Monitor/monitorPlugin.jarbin0 -> 95489 bytes
-rw-r--r--Article-Mutatis-mutandis/images/FieldEditorPreferenceHierarchy.GIFbin0 -> 2639 bytes
-rw-r--r--Article-Mutatis-mutandis/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Mutatis-mutandis/images/PreferencePage.GIFbin0 -> 47738 bytes
-rw-r--r--Article-Mutatis-mutandis/images/PropertyHierarchy.GIFbin0 -> 2689 bytes
-rw-r--r--Article-Mutatis-mutandis/images/PropertyPage.GIFbin0 -> 42026 bytes
-rw-r--r--Article-Mutatis-mutandis/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-Mutatis-mutandis/images/spellPreferences.GIFbin0 -> 37080 bytes
-rw-r--r--Article-Mutatis-mutandis/images/spellProperties.GIFbin0 -> 34058 bytes
-rw-r--r--Article-Mutatis-mutandis/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Mutatis-mutandis/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Mutatis-mutandis/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Mutatis-mutandis/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Mutatis-mutandis/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Mutatis-mutandis/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Mutatis-mutandis/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Mutatis-mutandis/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Mutatis-mutandis/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Mutatis-mutandis/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-Mutatis-mutandis/overlay-pages.html812
-rw-r--r--Article-Mutatis-mutandis/overlayPages.zipbin0 -> 8986 bytes
-rw-r--r--Article-Online Help for 1_0/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Online Help for 1_0/final.jpgbin0 -> 46096 bytes
-rw-r--r--Article-Online Help for 1_0/final.zipbin0 -> 6894 bytes
-rw-r--r--Article-Online Help for 1_0/help1.htm475
-rw-r--r--Article-Online Help for 1_0/initialstructure.zipbin0 -> 6894 bytes
-rw-r--r--Article-Online Help for 1_0/toplevel.jpgbin0 -> 5456 bytes
-rw-r--r--Article-Online Help for 2_0/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Online Help for 2_0/book.jpgbin0 -> 29016 bytes
-rw-r--r--Article-Online Help for 2_0/books.jpgbin0 -> 72224 bytes
-rw-r--r--Article-Online Help for 2_0/expanded_book.jpgbin0 -> 44433 bytes
-rw-r--r--Article-Online Help for 2_0/final.zipbin0 -> 8839 bytes
-rw-r--r--Article-Online Help for 2_0/final_ja_JP.zipbin0 -> 18607 bytes
-rw-r--r--Article-Online Help for 2_0/help1.htm358
-rw-r--r--Article-Online Help for 2_0/initialstructure.zipbin0 -> 7094 bytes
-rw-r--r--Article-Online Help for 2_0/zipped_plugin.zipbin0 -> 8392 bytes
-rw-r--r--Article-PDE-Automation/NoCVSConnStackTrace.txt243
-rw-r--r--Article-PDE-Automation/automation.html1568
-rw-r--r--Article-PDE-Automation/automation_style.css25
-rw-r--r--Article-PDE-Automation/buildInteractionDiagram.pngbin0 -> 11611 bytes
-rw-r--r--Article-PDE-Automation/buildRunConfiguration.pngbin0 -> 28029 bytes
-rw-r--r--Article-PDE-Automation/createAntBuildFile.pngbin0 -> 4569 bytes
-rw-r--r--Article-PDE-Automation/exportFeaturesDialog.pngbin0 -> 14125 bytes
-rw-r--r--Article-PDE-Automation/featureManifestEditor.pngbin0 -> 11712 bytes
-rw-r--r--Article-PDE-Automation/fetchProcessActivity.pngbin0 -> 9240 bytes
-rw-r--r--Article-PDE-Automation/figureOrdering.rb51
-rw-r--r--Article-PDE-Automation/runTestsInteractionDiagram.pngbin0 -> 7932 bytes
-rw-r--r--Article-PDE-Automation/runTestsRdtInteractionDiagram.pngbin0 -> 2695 bytes
-rw-r--r--Article-PDE-does-plugins/PDE-intro.html359
-rw-r--r--Article-PDE-does-plugins/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-PDE-does-plugins/images/compilers.gifbin0 -> 41136 bytes
-rw-r--r--Article-PDE-does-plugins/images/dependencies_page.gifbin0 -> 12575 bytes
-rw-r--r--Article-PDE-does-plugins/images/deploy.gifbin0 -> 30888 bytes
-rw-r--r--Article-PDE-does-plugins/images/dialog.gifbin0 -> 18771 bytes
-rw-r--r--Article-PDE-does-plugins/images/directory.gifbin0 -> 37900 bytes
-rw-r--r--Article-PDE-does-plugins/images/export_wizard.gifbin0 -> 37655 bytes
-rw-r--r--Article-PDE-does-plugins/images/extensions.gifbin0 -> 12391 bytes
-rw-r--r--Article-PDE-does-plugins/images/extensions2.gifbin0 -> 14141 bytes
-rw-r--r--Article-PDE-does-plugins/images/extensions3.gifbin0 -> 13207 bytes
-rw-r--r--Article-PDE-does-plugins/images/extensions4.gifbin0 -> 22002 bytes
-rw-r--r--Article-PDE-does-plugins/images/launcher_1.gifbin0 -> 44026 bytes
-rw-r--r--Article-PDE-does-plugins/images/plugin_project_1.gifbin0 -> 21656 bytes
-rw-r--r--Article-PDE-does-plugins/images/plugin_project_2.gifbin0 -> 57464 bytes
-rw-r--r--Article-PDE-does-plugins/images/project.gifbin0 -> 5137 bytes
-rw-r--r--Article-PDE-does-plugins/images/runtime_page.gifbin0 -> 17305 bytes
-rw-r--r--Article-PDE-does-plugins/images/sample_action_code.gifbin0 -> 7890 bytes
-rw-r--r--Article-PDE-does-plugins/images/target_platform.gifbin0 -> 49455 bytes
-rw-r--r--Article-PDE-does-plugins/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Plug-in-architecture/doc/allclasses-frame.html61
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/IProcessMember.html181
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/PrintMemberIdentity.html258
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/PrintMemberMenuAction.html280
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/ProcessExtensions.html219
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/class-use/IProcessMember.html150
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/class-use/PrintMemberIdentity.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/class-use/PrintMemberMenuAction.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/class-use/ProcessExtensions.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/package-frame.html41
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/package-summary.html164
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/package-tree.html111
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/demo/package-use.html123
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/firstlistener/ListenerX.html216
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/firstlistener/ListenerY.html216
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/firstlistener/class-use/ListenerX.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/firstlistener/class-use/ListenerY.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/firstlistener/package-frame.html28
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/firstlistener/package-summary.html130
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/firstlistener/package-tree.html106
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/firstlistener/package-use.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/secondlistener/ListenerX.html216
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/secondlistener/ListenerY.html216
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/secondlistener/class-use/ListenerX.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/secondlistener/class-use/ListenerY.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/secondlistener/package-frame.html28
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/secondlistener/package-summary.html130
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/secondlistener/package-tree.html106
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/secondlistener/package-use.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/subject/IListener.html175
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/subject/Subject.html248
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/subject/UpdateMenuAction.html276
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/subject/class-use/IListener.html140
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/subject/class-use/Subject.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/subject/class-use/UpdateMenuAction.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/subject/package-frame.html39
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/subject/package-summary.html146
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/subject/package-tree.html112
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/listener/subject/package-use.html122
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/echo/Echo.html224
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/echo/class-use/Echo.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/echo/package-frame.html26
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/echo/package-summary.html128
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/echo/package-tree.html105
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/echo/package-use.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/errortest/Dummy.html184
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/errortest/class-use/Dummy.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/errortest/package-frame.html26
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/errortest/package-summary.html128
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/errortest/package-tree.html104
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/errortest/package-use.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/exponentiation/Exponentiation.html271
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/exponentiation/class-use/Exponentiation.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/exponentiation/package-frame.html26
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/exponentiation/package-summary.html128
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/exponentiation/package-tree.html105
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/exponentiation/package-use.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/multiplication/Multiplication.html269
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/multiplication/class-use/Multiplication.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/multiplication/package-frame.html26
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/multiplication/package-summary.html128
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/multiplication/package-tree.html105
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/multiplication/package-use.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/FunctionsGrid.html229
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/FunctionsViewPart.html306
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/IFunction.html179
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/ProcessServiceMembers.html228
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/class-use/FunctionsGrid.html133
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/class-use/FunctionsViewPart.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/class-use/IFunction.html225
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/class-use/ProcessServiceMembers.html95
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/package-frame.html41
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/package-summary.html155
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/package-tree.html115
-rw-r--r--Article-Plug-in-architecture/doc/com/bolour/sample/eclipse/service/ui/package-use.html188
-rw-r--r--Article-Plug-in-architecture/doc/com_bolour_sample_eclipse_listener_subject_listeners.html63
-rw-r--r--Article-Plug-in-architecture/doc/com_bolour_sample_eclipse_service_ui_functions.html74
-rw-r--r--Article-Plug-in-architecture/doc/deprecated-list.html93
-rw-r--r--Article-Plug-in-architecture/doc/help-doc.html152
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-1.html96
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-10.html99
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-11.html111
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-12.html97
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-13.html99
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-2.html117
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-3.html105
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-4.html99
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-5.html99
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-6.html100
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-7.html120
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-8.html96
-rw-r--r--Article-Plug-in-architecture/doc/index-files/index-9.html120
-rw-r--r--Article-Plug-in-architecture/doc/index.html25
-rw-r--r--Article-Plug-in-architecture/doc/overview-frame.html52
-rw-r--r--Article-Plug-in-architecture/doc/overview-summary.html147
-rw-r--r--Article-Plug-in-architecture/doc/overview-tree.html126
-rw-r--r--Article-Plug-in-architecture/doc/package-list9
-rw-r--r--Article-Plug-in-architecture/doc/packages.html26
-rw-r--r--Article-Plug-in-architecture/doc/serialized-form.html93
-rw-r--r--Article-Plug-in-architecture/doc/stylesheet.css29
-rw-r--r--Article-Plug-in-architecture/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Plug-in-architecture/images/eclipse_extensions.jpgbin0 -> 63296 bytes
-rw-r--r--Article-Plug-in-architecture/images/functions_grid_view.jpgbin0 -> 61446 bytes
-rw-r--r--Article-Plug-in-architecture/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-Plug-in-architecture/images/listeners_extensions.jpgbin0 -> 69632 bytes
-rw-r--r--Article-Plug-in-architecture/images/services_extensions.jpgbin0 -> 67156 bytes
-rw-r--r--Article-Plug-in-architecture/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Plug-in-architecture/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Plug-in-architecture/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Plug-in-architecture/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Plug-in-architecture/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Plug-in-architecture/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Plug-in-architecture/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Plug-in-architecture/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Plug-in-architecture/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Plug-in-architecture/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-Plug-in-architecture/plugin_architecture.html2574
-rw-r--r--Article-Plug-in-architecture/samples.zipbin0 -> 63041 bytes
-rw-r--r--Article-Plug-in-architecture/specific_style.css4
-rw-r--r--Article-Plugging-into-SourceForge/images/SourceForge.net.pngbin0 -> 15619 bytes
-rw-r--r--Article-Plugging-into-SourceForge/images/WinSCP.pngbin0 -> 84258 bytes
-rw-r--r--Article-Plugging-into-SourceForge/images/cvs-view.pngbin0 -> 8128 bytes
-rw-r--r--Article-Plugging-into-SourceForge/images/frs.pngbin0 -> 4798 bytes
-rw-r--r--Article-Plugging-into-SourceForge/images/new-cvs.pngbin0 -> 10188 bytes
-rw-r--r--Article-Plugging-into-SourceForge/images/sfpde-med.pngbin0 -> 82321 bytes
-rw-r--r--Article-Plugging-into-SourceForge/images/working-set.pngbin0 -> 43281 bytes
-rw-r--r--Article-Plugging-into-SourceForge/sourceforge.html935
-rw-r--r--Article-Preferences/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Preferences/images/badwordpreference.gifbin0 -> 13269 bytes
-rw-r--r--Article-Preferences/images/colorpreference.gifbin0 -> 12515 bytes
-rw-r--r--Article-Preferences/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Preferences/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Preferences/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Preferences/images/tree.gifbin0 -> 4415 bytes
-rw-r--r--Article-Preferences/preferences.htm414
-rw-r--r--Article-Preferences/preferences.zipbin0 -> 7985 bytes
-rw-r--r--Article-Properties-View/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Properties-View/images/default.jpgbin0 -> 3135 bytes
-rw-r--r--Article-Properties-View/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-Properties-View/images/properties.jpgbin0 -> 65343 bytes
-rw-r--r--Article-Properties-View/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Properties-View/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Properties-View/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Properties-View/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Properties-View/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Properties-View/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Properties-View/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Properties-View/images/tag_a.jpgbin0 -> 916 bytes
-rw-r--r--Article-Properties-View/images/tag_b.jpgbin0 -> 924 bytes
-rw-r--r--Article-Properties-View/images/tag_c.jpgbin0 -> 913 bytes
-rw-r--r--Article-Properties-View/images/tag_d.jpgbin0 -> 914 bytes
-rw-r--r--Article-Properties-View/images/tag_e.jpgbin0 -> 909 bytes
-rw-r--r--Article-Properties-View/images/tag_f.jpgbin0 -> 893 bytes
-rw-r--r--Article-Properties-View/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Properties-View/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Properties-View/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-Properties-View/properties-view.html412
-rw-r--r--Article-Properties-View/properties-view.jpgbin0 -> 14902 bytes
-rw-r--r--Article-Properties-View/propertyviewsample.zipbin0 -> 20637 bytes
-rw-r--r--Article-RCP-1/images/spin.pngbin0 -> 6441 bytes
-rw-r--r--Article-RCP-1/part1.zipbin0 -> 11867 bytes
-rw-r--r--Article-RCP-1/tutorial1.html382
-rw-r--r--Article-RCP-2/images/manifest-editor-overview.pngbin0 -> 38290 bytes
-rw-r--r--Article-RCP-2/part2.zipbin0 -> 11870 bytes
-rw-r--r--Article-RCP-2/tutorial2.html918
-rw-r--r--Article-RCP-3/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-RCP-3/images/complete.pngbin0 -> 10185 bytes
-rw-r--r--Article-RCP-3/images/help.pngbin0 -> 16221 bytes
-rw-r--r--Article-RCP-3/images/note.gifbin0 -> 1014 bytes
-rw-r--r--Article-RCP-3/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-RCP-3/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-RCP-3/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-RCP-3/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-RCP-3/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-RCP-3/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-RCP-3/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-RCP-3/tutorial3.html518
-rw-r--r--Article-Resource-deltas/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Resource-deltas/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Resource-deltas/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Resource-deltas/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Resource-deltas/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Resource-deltas/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Resource-deltas/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Resource-deltas/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Resource-deltas/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Resource-deltas/images/tree-before.jpgbin0 -> 6139 bytes
-rw-r--r--Article-Resource-deltas/images/tree-delta.jpgbin0 -> 7446 bytes
-rw-r--r--Article-Resource-deltas/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Resource-deltas/resource-deltas.html597
-rw-r--r--Article-Rule Modeling With EMF/BallPlacementRuleModel.zipbin0 -> 1343 bytes
-rw-r--r--Article-Rule Modeling With EMF/RuleMetaModel.zipbin0 -> 257182 bytes
-rw-r--r--Article-Rule Modeling With EMF/article.html614
-rw-r--r--Article-Rule Modeling With EMF/images/BallPlacementResult.gifbin0 -> 11574 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/ClassDiagram1.gifbin0 -> 11136 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/ClassDiagram2.gifbin0 -> 3985 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/Overall.gifbin0 -> 15095 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/RuleMetaModel.gifbin0 -> 21962 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/RuleModel.gifbin0 -> 16945 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Rule Modeling With EMF/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-SWT-Color-Model/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-SWT-Color-Model/about.xml24
-rw-r--r--Article-SWT-Color-Model/swt-color-model.htm346
-rw-r--r--Article-SWT-DND/DND-in-SWT.html1739
-rw-r--r--Article-SWT-DND/about.xml26
-rw-r--r--Article-SWT-DND/images/dnd1.gifbin0 -> 12482 bytes
-rw-r--r--Article-SWT-DND/images/idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-SWT-DND/images/image001.gifbin0 -> 12482 bytes
-rw-r--r--Article-SWT-DND/images/image002.gifbin0 -> 31216 bytes
-rw-r--r--Article-SWT-DND/images/image002.jpgbin0 -> 25326 bytes
-rw-r--r--Article-SWT-DND/images/image003.pngbin0 -> 290 bytes
-rw-r--r--Article-SWT-DND/images/image004.jpgbin0 -> 527 bytes
-rw-r--r--Article-SWT-DND/images/image005.GIFbin0 -> 947 bytes
-rw-r--r--Article-SWT-DND/images/image005.pngbin0 -> 351 bytes
-rw-r--r--Article-SWT-DND/images/image006.jpgbin0 -> 622 bytes
-rw-r--r--Article-SWT-DND/images/image007.pngbin0 -> 349 bytes
-rw-r--r--Article-SWT-DND/images/image008.jpgbin0 -> 632 bytes
-rw-r--r--Article-SWT-DND/images/image009.pngbin0 -> 244 bytes
-rw-r--r--Article-SWT-DND/images/image010.jpgbin0 -> 526 bytes
-rw-r--r--Article-SWT-Design-1/SWT-Design-1.html310
-rw-r--r--Article-SWT-Design-1/about.xml38
-rw-r--r--Article-SWT-Design-1/default_style.css11
-rw-r--r--Article-SWT-Design-1/idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-SWT-OpenGL/images/1W08-2.pngbin0 -> 70250 bytes
-rw-r--r--Article-SWT-OpenGL/images/3dchart4.pngbin0 -> 67234 bytes
-rw-r--r--Article-SWT-OpenGL/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-SWT-OpenGL/images/cylinder.pngbin0 -> 1724 bytes
-rw-r--r--Article-SWT-OpenGL/images/gl_command.pngbin0 -> 5495 bytes
-rw-r--r--Article-SWT-OpenGL/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-SWT-OpenGL/images/rotation.xcfbin0 -> 19216 bytes
-rw-r--r--Article-SWT-OpenGL/images/rotation3.pngbin0 -> 11484 bytes
-rw-r--r--Article-SWT-OpenGL/images/rotation4.pngbin0 -> 14316 bytes
-rw-r--r--Article-SWT-OpenGL/images/rotation5.pngbin0 -> 6899 bytes
-rw-r--r--Article-SWT-OpenGL/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-SWT-OpenGL/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-SWT-OpenGL/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-SWT-OpenGL/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-SWT-OpenGL/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-SWT-OpenGL/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-SWT-OpenGL/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-SWT-OpenGL/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-SWT-OpenGL/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-SWT-OpenGL/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-SWT-OpenGL/images/workbench2.pngbin0 -> 68746 bytes
-rw-r--r--Article-SWT-OpenGL/images/workbench3.pngbin0 -> 46790 bytes
-rw-r--r--Article-SWT-OpenGL/lib/demo_plugin.zipbin0 -> 34535 bytes
-rw-r--r--Article-SWT-OpenGL/opengl.css201
-rw-r--r--Article-SWT-OpenGL/opengl.html1248
-rw-r--r--Article-SWT-browser-widget/DocumentationViewer.java152
-rw-r--r--Article-SWT-browser-widget/about.xml15
-rw-r--r--Article-SWT-browser-widget/browser.html191
-rw-r--r--Article-SWT-browser-widget/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-SWT-browser-widget/images/help_browser.pngbin0 -> 45474 bytes
-rw-r--r--Article-SWT-browser-widget/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-SWT-browser-widget/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-SWT-browser-widget/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-SWT-browser-widget/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-SWT-browser-widget/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-SWT-browser-widget/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-SWT-browser-widget/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-SWT-browser-widget/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-SWT-browser-widget/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-SWT-browser-widget/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-SWT-browser-widget/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-SWT-graphics/SWT_graphics.html629
-rw-r--r--Article-SWT-graphics/about.xml33
-rw-r--r--Article-SWT-graphics/images/ArcClient.gifbin0 -> 1553 bytes
-rw-r--r--Article-SWT-graphics/images/ArcFilledClient.gifbin0 -> 1525 bytes
-rw-r--r--Article-SWT-graphics/images/Cheese_Complete.gifbin0 -> 29459 bytes
-rw-r--r--Article-SWT-graphics/images/ClippedTriangles.gifbin0 -> 14407 bytes
-rw-r--r--Article-SWT-graphics/images/GradientFillFalse.gifbin0 -> 2527 bytes
-rw-r--r--Article-SWT-graphics/images/GradientFillTrue.gifbin0 -> 2518 bytes
-rw-r--r--Article-SWT-graphics/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-SWT-graphics/images/ImageClient.jpgbin0 -> 6114 bytes
-rw-r--r--Article-SWT-graphics/images/ImageClientStretched.jpgbin0 -> 6476 bytes
-rw-r--r--Article-SWT-graphics/images/ImageClipped.jpgbin0 -> 9555 bytes
-rw-r--r--Article-SWT-graphics/images/LINE_DASH.gifbin0 -> 945 bytes
-rw-r--r--Article-SWT-graphics/images/LINE_DASHDOT.gifbin0 -> 957 bytes
-rw-r--r--Article-SWT-graphics/images/LINE_DASHDOTDOT.gifbin0 -> 967 bytes
-rw-r--r--Article-SWT-graphics/images/LINE_DOT.gifbin0 -> 962 bytes
-rw-r--r--Article-SWT-graphics/images/LineShapes.gifbin0 -> 1730 bytes
-rw-r--r--Article-SWT-graphics/images/Line_SOLID.gifbin0 -> 930 bytes
-rw-r--r--Article-SWT-graphics/images/OvalClient.gifbin0 -> 1495 bytes
-rw-r--r--Article-SWT-graphics/images/OvalFilledClient.gifbin0 -> 1476 bytes
-rw-r--r--Article-SWT-graphics/images/PolygonClient.gifbin0 -> 1487 bytes
-rw-r--r--Article-SWT-graphics/images/PolygonFillClient.gifbin0 -> 1501 bytes
-rw-r--r--Article-SWT-graphics/images/RectangleClient.gifbin0 -> 1567 bytes
-rw-r--r--Article-SWT-graphics/images/RectangleFillClient.gifbin0 -> 1483 bytes
-rw-r--r--Article-SWT-graphics/images/RectangleStrokeFill.gifbin0 -> 1586 bytes
-rw-r--r--Article-SWT-graphics/images/RoundedRectangleClient.gifbin0 -> 3059 bytes
-rw-r--r--Article-SWT-graphics/images/RoundedRectangleFilledClient.gifbin0 -> 1486 bytes
-rw-r--r--Article-SWT-graphics/images/ShellDrawnLine.gifbin0 -> 5034 bytes
-rw-r--r--Article-SWT-graphics/images/StringHelloWorld.gifbin0 -> 1952 bytes
-rw-r--r--Article-SWT-graphics/images/TextFlags.gifbin0 -> 13430 bytes
-rw-r--r--Article-SWT-graphics/images/TextHelloWorld.gifbin0 -> 1974 bytes
-rw-r--r--Article-SWT-graphics/images/TextHelloWorldTransparent.gifbin0 -> 13722 bytes
-rw-r--r--Article-SWT-graphics/images/Width_2.gifbin0 -> 940 bytes
-rw-r--r--Article-SWT-graphics/images/Width_4.gifbin0 -> 952 bytes
-rw-r--r--Article-SWT-graphics/images/XORFills.gifbin0 -> 2258 bytes
-rw-r--r--Article-SWT-graphics/images/default_style.css11
-rw-r--r--Article-SWT-graphics/images/image_lg_lines.gifbin0 -> 13615 bytes
-rw-r--r--Article-SWT-graphics/images/image_lg_orig.gifbin0 -> 13359 bytes
-rw-r--r--Article-SWT-graphics/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-SWT-graphics/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-SWT-graphics/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-SWT-graphics/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-SWT-graphics/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-SWT-graphics/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-SWT-graphics/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-SWT-graphics/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-SWT-graphics/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-SWT-graphics/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-SWT-graphics/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-SWT-images/graphics-resources.html1050
-rw-r--r--Article-SWT-images/images/AlphaImages.gifbin0 -> 12092 bytes
-rw-r--r--Article-SWT-images/images/AnimationFrames.gifbin0 -> 79733 bytes
-rw-r--r--Article-SWT-images/images/BlendedImage.gifbin0 -> 7884 bytes
-rw-r--r--Article-SWT-images/images/BlendedImageOnSplash.gifbin0 -> 90231 bytes
-rw-r--r--Article-SWT-images/images/ButonLogo.gifbin0 -> 20478 bytes
-rw-r--r--Article-SWT-images/images/CustomCursor.gifbin0 -> 5195 bytes
-rw-r--r--Article-SWT-images/images/DirectPalette.gifbin0 -> 3030 bytes
-rw-r--r--Article-SWT-images/images/DirectPalette_01.gifbin0 -> 3750 bytes
-rw-r--r--Article-SWT-images/images/DirectPalette_02.gifbin0 -> 3751 bytes
-rw-r--r--Article-SWT-images/images/EclipseBannerPic.gifbin0 -> 3674 bytes
-rw-r--r--Article-SWT-images/images/EclipseBannerPic.jpgbin0 -> 2011 bytes
-rw-r--r--Article-SWT-images/images/Fonts.gifbin0 -> 9579 bytes
-rw-r--r--Article-SWT-images/images/GraphicsEffects_01.JPGbin0 -> 48865 bytes
-rw-r--r--Article-SWT-images/images/Idea.gifbin0 -> 6842 bytes
-rw-r--r--Article-SWT-images/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-SWT-images/images/IdeaTransparency.gifbin0 -> 19778 bytes
-rw-r--r--Article-SWT-images/images/Idea_AndSWTText.gifbin0 -> 1189 bytes
-rw-r--r--Article-SWT-images/images/Idea_EclipseText.gifbin0 -> 1142 bytes
-rw-r--r--Article-SWT-images/images/Idea_HalfSize.gifbin0 -> 1533 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original.gifbin0 -> 7667 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_01.gifbin0 -> 5816 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_A.gifbin0 -> 7023 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_B.gifbin0 -> 6456 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_C.gifbin0 -> 6461 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_D.gifbin0 -> 6543 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_E.gifbin0 -> 6839 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_F.gifbin0 -> 6543 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_G.gifbin0 -> 7562 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_H.gifbin0 -> 6569 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_I.gifbin0 -> 6707 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_J.gifbin0 -> 6548 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_K.gifbin0 -> 6720 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_L.gifbin0 -> 6544 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_M.gifbin0 -> 6715 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_N.gifbin0 -> 6844 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_O.gifbin0 -> 6755 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_P.gifbin0 -> 7638 bytes
-rw-r--r--Article-SWT-images/images/Idea_Original_Q.gifbin0 -> 6053 bytes
-rw-r--r--Article-SWT-images/images/Idea_Pen.gifbin0 -> 3202 bytes
-rw-r--r--Article-SWT-images/images/Idea_SWT_Animation.gifbin0 -> 70705 bytes
-rw-r--r--Article-SWT-images/images/Idea_Transparent_DrawnOnCanvas.gifbin0 -> 11461 bytes
-rw-r--r--Article-SWT-images/images/Idea_animated.gifbin0 -> 11920 bytes
-rw-r--r--Article-SWT-images/images/Idea_transparent.jpgbin0 -> 2931 bytes
-rw-r--r--Article-SWT-images/images/ImageBlended.gifbin0 -> 13511 bytes
-rw-r--r--Article-SWT-images/images/ImageEffects.jpgbin0 -> 7281 bytes
-rw-r--r--Article-SWT-images/images/Image_NS.gifbin0 -> 882 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_E.gifbin0 -> 878 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_N.gifbin0 -> 882 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_NESW.gifbin0 -> 876 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_NW.gifbin0 -> 878 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_S.gifbin0 -> 882 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_SE.gifbin0 -> 879 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_SW.gifbin0 -> 878 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_W.gifbin0 -> 879 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_appstarting.gifbin0 -> 930 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_arrow.gifbin0 -> 905 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_busy.gifbin0 -> 918 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_cross.gifbin0 -> 880 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_hand.gifbin0 -> 914 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_help.gifbin0 -> 926 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_ibeam.gifbin0 -> 881 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_not.gifbin0 -> 917 bytes
-rw-r--r--Article-SWT-images/images/Image_cursor_sizeall.gifbin0 -> 892 bytes
-rw-r--r--Article-SWT-images/images/Image_size_NE.gifbin0 -> 879 bytes
-rw-r--r--Article-SWT-images/images/Imagecursor_uparrow.gifbin0 -> 878 bytes
-rw-r--r--Article-SWT-images/images/IntroductionRelativeIcon.gifbin0 -> 7815 bytes
-rw-r--r--Article-SWT-images/images/IveBeenDrawnOn.gifbin0 -> 20743 bytes
-rw-r--r--Article-SWT-images/images/LabelCanvasTransparent.gifbin0 -> 9121 bytes
-rw-r--r--Article-SWT-images/images/Note.gifbin0 -> 1014 bytes
-rw-r--r--Article-SWT-images/images/RedGreenImage.gifbin0 -> 930 bytes
-rw-r--r--Article-SWT-images/images/RelativeLogo.gifbin0 -> 8395 bytes
-rw-r--r--Article-SWT-images/images/ScaledGraphics.gifbin0 -> 34718 bytes
-rw-r--r--Article-SWT-images/images/ScaledImages.gifbin0 -> 134937 bytes
-rw-r--r--Article-SWT-images/images/ScaledImages_01.gifbin0 -> 38796 bytes
-rw-r--r--Article-SWT-images/images/ShellCursors.gifbin0 -> 10915 bytes
-rw-r--r--Article-SWT-images/images/SingleAlphaChannel.gifbin0 -> 27167 bytes
-rw-r--r--Article-SWT-images/images/TimesFont.gifbin0 -> 7050 bytes
-rw-r--r--Article-SWT-images/images/TransparentIdea.gifbin0 -> 17441 bytes
-rw-r--r--Article-SWT-images/images/javalogo.gifbin0 -> 2260 bytes
-rw-r--r--Article-SWT-images/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-SWT-images/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-SWT-images/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-SWT-images/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-SWT-images/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-SWT-images/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-SWT-images/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-TVT/eclipse_tvt.zipbin0 -> 46145 bytes
-rw-r--r--Article-TVT/how2TestI18n.html493
-rw-r--r--Article-TVT/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-TVT/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-TVT/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-TVT/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-TVT/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-TVT/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-TVT/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-TVT/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-TVT/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-TVT/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-TVT/images/tool.jpgbin0 -> 126083 bytes
-rw-r--r--Article-TVT/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-TVT/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-Table-viewer/TableViewerExamplePlugin.zipbin0 -> 25942 bytes
-rw-r--r--Article-Table-viewer/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Table-viewer/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-Table-viewer/images/tableViewer.gifbin0 -> 11232 bytes
-rw-r--r--Article-Table-viewer/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Table-viewer/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Table-viewer/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Table-viewer/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Table-viewer/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Table-viewer/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Table-viewer/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Table-viewer/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Table-viewer/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Table-viewer/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-Table-viewer/table_viewer.html500
-rw-r--r--Article-UI-Guidelines/Contents.html5839
-rw-r--r--Article-UI-Guidelines/Index.html8
-rw-r--r--Article-UI-Guidelines/Toc.html218
-rw-r--r--Article-UI-Guidelines/default_style.css17
-rw-r--r--Article-UI-Guidelines/images/256palette.gifbin0 -> 11287 bytes
-rw-r--r--Article-UI-Guidelines/images/Idea.gifbin0 -> 7163 bytes
-rw-r--r--Article-UI-Guidelines/images/actionExamples.gifbin0 -> 80129 bytes
-rw-r--r--Article-UI-Guidelines/images/badHilight.gifbin0 -> 38153 bytes
-rw-r--r--Article-UI-Guidelines/images/badTooltips.gifbin0 -> 16492 bytes
-rw-r--r--Article-UI-Guidelines/images/badWizardInit.gifbin0 -> 12402 bytes
-rw-r--r--Article-UI-Guidelines/images/bp1.gifbin0 -> 41874 bytes
-rw-r--r--Article-UI-Guidelines/images/bp2.gifbin0 -> 43970 bytes
-rw-r--r--Article-UI-Guidelines/images/bp3.gifbin0 -> 42378 bytes
-rw-r--r--Article-UI-Guidelines/images/bp4.gifbin0 -> 47214 bytes
-rw-r--r--Article-UI-Guidelines/images/bp5.gifbin0 -> 44818 bytes
-rw-r--r--Article-UI-Guidelines/images/bp6.gifbin0 -> 48929 bytes
-rw-r--r--Article-UI-Guidelines/images/cell1.gifbin0 -> 288 bytes
-rw-r--r--Article-UI-Guidelines/images/cell2.gifbin0 -> 3412 bytes
-rw-r--r--Article-UI-Guidelines/images/cell3.gifbin0 -> 276 bytes
-rw-r--r--Article-UI-Guidelines/images/cellTableEditor.gifbin0 -> 31810 bytes
-rw-r--r--Article-UI-Guidelines/images/dirtyEditor.gifbin0 -> 20561 bytes
-rw-r--r--Article-UI-Guidelines/images/disabledcolors.gifbin0 -> 1124 bytes
-rw-r--r--Article-UI-Guidelines/images/editorTitles.gifbin0 -> 7770 bytes
-rw-r--r--Article-UI-Guidelines/images/enabledcolors.gifbin0 -> 4475 bytes
-rw-r--r--Article-UI-Guidelines/images/errorsInOutline.gifbin0 -> 14744 bytes
-rw-r--r--Article-UI-Guidelines/images/fileDeletedDialog.gifbin0 -> 16401 bytes
-rw-r--r--Article-UI-Guidelines/images/flatlook1.gifbin0 -> 64142 bytes
-rw-r--r--Article-UI-Guidelines/images/flatlook2.gifbin0 -> 4244 bytes
-rw-r--r--Article-UI-Guidelines/images/flatlook3.gifbin0 -> 28337 bytes
-rw-r--r--Article-UI-Guidelines/images/flatlook4.gifbin0 -> 15874 bytes
-rw-r--r--Article-UI-Guidelines/images/flatlook5.gifbin0 -> 17162 bytes
-rw-r--r--Article-UI-Guidelines/images/flatlook6.gifbin0 -> 41600 bytes
-rw-r--r--Article-UI-Guidelines/images/flatlook7.gifbin0 -> 10090 bytes
-rw-r--r--Article-UI-Guidelines/images/flatlook8.gifbin0 -> 5954 bytes
-rw-r--r--Article-UI-Guidelines/images/flatlook9.gifbin0 -> 16190 bytes
-rw-r--r--Article-UI-Guidelines/images/folderSelection.gifbin0 -> 93567 bytes
-rw-r--r--Article-UI-Guidelines/images/goodParentCreation.gifbin0 -> 12741 bytes
-rw-r--r--Article-UI-Guidelines/images/goodTooltips.gifbin0 -> 7981 bytes
-rw-r--r--Article-UI-Guidelines/images/goodWizardInit.gifbin0 -> 10768 bytes
-rw-r--r--Article-UI-Guidelines/images/guidelineCheckbox.gifbin0 -> 87 bytes
-rw-r--r--Article-UI-Guidelines/images/guidelineIndicator.gifbin0 -> 83 bytes
-rw-r--r--Article-UI-Guidelines/images/icon_types.gifbin0 -> 19275 bytes
-rw-r--r--Article-UI-Guidelines/images/iconposition_main.gifbin0 -> 20302 bytes
-rw-r--r--Article-UI-Guidelines/images/impready_folderstructure.gifbin0 -> 5504 bytes
-rw-r--r--Article-UI-Guidelines/images/metaphor_concepts.gifbin0 -> 21137 bytes
-rw-r--r--Article-UI-Guidelines/images/overlay_realestate.gifbin0 -> 1035 bytes
-rw-r--r--Article-UI-Guidelines/images/ovr_auxiliary.gifbin0 -> 2237 bytes
-rw-r--r--Article-UI-Guidelines/images/ovr_java.gifbin0 -> 3997 bytes
-rw-r--r--Article-UI-Guidelines/images/ovr_java_sample1.gifbin0 -> 5389 bytes
-rw-r--r--Article-UI-Guidelines/images/ovr_projectnature.gifbin0 -> 2276 bytes
-rw-r--r--Article-UI-Guidelines/images/ovr_projectnature_sample.gifbin0 -> 3758 bytes
-rw-r--r--Article-UI-Guidelines/images/ovr_versioncontrol.gifbin0 -> 2547 bytes
-rw-r--r--Article-UI-Guidelines/images/ovr_versioncontrol_cvs.gifbin0 -> 3267 bytes
-rw-r--r--Article-UI-Guidelines/images/ovr_versioncontrol_cvs_samp.gifbin0 -> 5630 bytes
-rw-r--r--Article-UI-Guidelines/images/perspective_realestate.gifbin0 -> 1516 bytes
-rw-r--r--Article-UI-Guidelines/images/perspective_specs.gifbin0 -> 7436 bytes
-rw-r--r--Article-UI-Guidelines/images/run_co.gifbin0 -> 116 bytes
-rw-r--r--Article-UI-Guidelines/images/showViewMenu.gifbin0 -> 29710 bytes
-rw-r--r--Article-UI-Guidelines/images/slushBucket.gifbin0 -> 31962 bytes
-rw-r--r--Article-UI-Guidelines/images/synch_co.gifbin0 -> 110 bytes
-rw-r--r--Article-UI-Guidelines/images/titlebar_specs.gifbin0 -> 5262 bytes
-rw-r--r--Article-UI-Guidelines/images/toolbar_realestate.gifbin0 -> 1469 bytes
-rw-r--r--Article-UI-Guidelines/images/toolbar_specs.gifbin0 -> 9769 bytes
-rw-r--r--Article-UI-Guidelines/images/tooltipCaps.gifbin0 -> 11297 bytes
-rw-r--r--Article-UI-Guidelines/images/treeview_specs.gifbin0 -> 5500 bytes
-rw-r--r--Article-UI-Guidelines/images/view_realestate.gifbin0 -> 1492 bytes
-rw-r--r--Article-UI-Guidelines/images/wizardAppearance.gifbin0 -> 16676 bytes
-rw-r--r--Article-UI-Guidelines/images/wizardErrorMsgs.gifbin0 -> 24569 bytes
-rw-r--r--Article-UI-Guidelines/images/wizardErrorMsgs2.gifbin0 -> 11609 bytes
-rw-r--r--Article-UI-Guidelines/images/wizardFieldPopulation.gifbin0 -> 25649 bytes
-rw-r--r--Article-UI-Guidelines/images/wizardMsgs.gifbin0 -> 6705 bytes
-rw-r--r--Article-UI-Guidelines/images/wizban.gifbin0 -> 6613 bytes
-rw-r--r--Article-UI-Guidelines/images/wizban183.gifbin0 -> 8274 bytes
-rw-r--r--Article-UI-Guidelines/images/wizbans.gifbin0 -> 8575 bytes
-rw-r--r--Article-UI-Guidelines/images/workbench_decomposed.gifbin0 -> 65302 bytes
-rw-r--r--Article-UI-Guidelines/v200202/Contents.html3887
-rw-r--r--Article-UI-Guidelines/v200202/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-UI-Guidelines/v200202/Index.html10
-rw-r--r--Article-UI-Guidelines/v200202/Toc.html162
-rw-r--r--Article-UI-Guidelines/v200202/actionExamples.jpgbin0 -> 58510 bytes
-rw-r--r--Article-UI-Guidelines/v200202/badHilight.jpgbin0 -> 123041 bytes
-rw-r--r--Article-UI-Guidelines/v200202/badTooltips.jpgbin0 -> 42978 bytes
-rw-r--r--Article-UI-Guidelines/v200202/badWizardInit.jpgbin0 -> 36320 bytes
-rw-r--r--Article-UI-Guidelines/v200202/cell1.jpgbin0 -> 1362 bytes
-rw-r--r--Article-UI-Guidelines/v200202/cell2.jpgbin0 -> 2210 bytes
-rw-r--r--Article-UI-Guidelines/v200202/cell3.jpgbin0 -> 1301 bytes
-rw-r--r--Article-UI-Guidelines/v200202/cellTableEditor.jpgbin0 -> 21858 bytes
-rw-r--r--Article-UI-Guidelines/v200202/default_style.css11
-rw-r--r--Article-UI-Guidelines/v200202/dirtyEditor.jpgbin0 -> 72691 bytes
-rw-r--r--Article-UI-Guidelines/v200202/editorTitles.jpgbin0 -> 22301 bytes
-rw-r--r--Article-UI-Guidelines/v200202/errorsInOutline.jpgbin0 -> 53089 bytes
-rw-r--r--Article-UI-Guidelines/v200202/fileDeletedDialog.jpgbin0 -> 39046 bytes
-rw-r--r--Article-UI-Guidelines/v200202/folderSelection.jpgbin0 -> 279122 bytes
-rw-r--r--Article-UI-Guidelines/v200202/goodParentCreation.jpgbin0 -> 50982 bytes
-rw-r--r--Article-UI-Guidelines/v200202/goodTooltips.jpgbin0 -> 57201 bytes
-rw-r--r--Article-UI-Guidelines/v200202/goodWizardInit.jpgbin0 -> 33050 bytes
-rw-r--r--Article-UI-Guidelines/v200202/guidelineCheckbox.jpgbin0 -> 2654 bytes
-rw-r--r--Article-UI-Guidelines/v200202/guidelineIndicator.gifbin0 -> 83 bytes
-rw-r--r--Article-UI-Guidelines/v200202/showViewMenu.jpgbin0 -> 170443 bytes
-rw-r--r--Article-UI-Guidelines/v200202/slushBucket.jpgbin0 -> 28643 bytes
-rw-r--r--Article-UI-Guidelines/v200202/tooltipCaps.jpgbin0 -> 30396 bytes
-rw-r--r--Article-UI-Guidelines/v200202/wizardAppearance.jpgbin0 -> 56185 bytes
-rw-r--r--Article-UI-Guidelines/v200202/wizardErrorMsgs.jpgbin0 -> 120906 bytes
-rw-r--r--Article-UI-Guidelines/v200202/wizardErrorMsgs2.jpgbin0 -> 56330 bytes
-rw-r--r--Article-UI-Guidelines/v200202/wizardFieldPopulation.jpgbin0 -> 88886 bytes
-rw-r--r--Article-UI-Guidelines/v200202/wizardMsgs.jpgbin0 -> 22518 bytes
-rw-r--r--Article-UI-Guidelines/v200202/workbench_decomposed.jpgbin0 -> 55919 bytes
-rw-r--r--Article-UI-Workbench/images/LayoutPart_hierarchy.pngbin0 -> 7493 bytes
-rw-r--r--Article-UI-Workbench/images/PartSashContainer.pngbin0 -> 7006 bytes
-rw-r--r--Article-UI-Workbench/images/PartStack.pngbin0 -> 4800 bytes
-rw-r--r--Article-UI-Workbench/images/action_bar_flow.pngbin0 -> 21585 bytes
-rw-r--r--Article-UI-Workbench/images/action_set_formula.pngbin0 -> 807 bytes
-rw-r--r--Article-UI-Workbench/images/anatomy_of_a_part.pngbin0 -> 6203 bytes
-rw-r--r--Article-UI-Workbench/images/drag_regions.pngbin0 -> 119057 bytes
-rw-r--r--Article-UI-Workbench/images/example_LayoutTree.pngbin0 -> 12016 bytes
-rw-r--r--Article-UI-Workbench/images/left_arrow.pngbin0 -> 248 bytes
-rw-r--r--Article-UI-Workbench/images/part_creation_msc.pngbin0 -> 28578 bytes
-rw-r--r--Article-UI-Workbench/images/part_states.pngbin0 -> 13834 bytes
-rw-r--r--Article-UI-Workbench/images/perspective1.pngbin0 -> 44076 bytes
-rw-r--r--Article-UI-Workbench/images/perspective1_2_instances.pngbin0 -> 23547 bytes
-rw-r--r--Article-UI-Workbench/images/perspective2.pngbin0 -> 37110 bytes
-rw-r--r--Article-UI-Workbench/images/right_arrow.pngbin0 -> 245 bytes
-rw-r--r--Article-UI-Workbench/images/what_you_see.pngbin0 -> 81123 bytes
-rw-r--r--Article-UI-Workbench/images/workbench_high_level.pngbin0 -> 9113 bytes
-rw-r--r--Article-UI-Workbench/workbench.html1112
-rw-r--r--Article-Understanding Layouts/Understanding Layouts.htm3882
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/default_style.css11
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/filelist.xml84
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/header.htm69
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image001.pngbin0 -> 9166 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image002.jpgbin0 -> 21962 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image003.pngbin0 -> 978 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image004.jpgbin0 -> 3305 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image005.pngbin0 -> 1081 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image006.jpgbin0 -> 3285 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image007.pngbin0 -> 888 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image008.jpgbin0 -> 2836 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image009.pngbin0 -> 1004 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image010.jpgbin0 -> 3614 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image011.pngbin0 -> 985 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image012.jpgbin0 -> 3024 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image013.pngbin0 -> 1030 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image014.jpgbin0 -> 4298 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image015.pngbin0 -> 2084 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image016.jpgbin0 -> 7423 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image017.pngbin0 -> 957 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image018.jpgbin0 -> 3305 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image019.pngbin0 -> 1062 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image020.jpgbin0 -> 3344 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image021.jpgbin0 -> 3305 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image022.pngbin0 -> 982 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image023.jpgbin0 -> 3083 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image024.pngbin0 -> 1018 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image025.jpgbin0 -> 3003 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image026.pngbin0 -> 1131 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image027.jpgbin0 -> 4046 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image028.pngbin0 -> 956 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image029.jpgbin0 -> 3266 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image030.pngbin0 -> 991 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image031.jpgbin0 -> 3104 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image032.pngbin0 -> 1039 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image033.jpgbin0 -> 3750 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image034.pngbin0 -> 1335 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image035.jpgbin0 -> 4284 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image036.pngbin0 -> 1260 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image037.jpgbin0 -> 4396 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image038.pngbin0 -> 1214 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image039.jpgbin0 -> 4450 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image040.pngbin0 -> 3220 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image041.jpgbin0 -> 8370 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image042.pngbin0 -> 1352 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image043.jpgbin0 -> 4587 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image044.pngbin0 -> 1369 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image045.jpgbin0 -> 4559 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image046.pngbin0 -> 1368 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image047.jpgbin0 -> 4570 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image048.pngbin0 -> 1366 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image049.jpgbin0 -> 4651 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image050.pngbin0 -> 1799 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image051.jpgbin0 -> 4570 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image052.pngbin0 -> 1776 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image053.jpgbin0 -> 4805 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image054.pngbin0 -> 1648 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image055.jpgbin0 -> 4459 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image056.pngbin0 -> 1832 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image057.jpgbin0 -> 4693 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image058.jpgbin0 -> 4693 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image059.pngbin0 -> 1992 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image060.jpgbin0 -> 4944 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image061.pngbin0 -> 1399 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image062.jpgbin0 -> 5285 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image063.pngbin0 -> 785 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image064.jpgbin0 -> 2317 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image065.pngbin0 -> 883 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image066.jpgbin0 -> 3643 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image067.jpgbin0 -> 4450 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image068.pngbin0 -> 1308 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image069.jpgbin0 -> 4635 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image070.gifbin0 -> 7016 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image071.pngbin0 -> 11638 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image072.jpgbin0 -> 21205 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image073.pngbin0 -> 12303 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image074.jpgbin0 -> 23383 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image075.pngbin0 -> 1510 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image076.jpgbin0 -> 5694 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image077.pngbin0 -> 1743 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/image078.jpgbin0 -> 6677 bytes
-rw-r--r--Article-Understanding Layouts/Understanding Layouts_files/oledata.msobin0 -> 18944 bytes
-rw-r--r--Article-Update/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Update/images/category-def.jpgbin0 -> 32256 bytes
-rw-r--r--Article-Update/images/copyright.jpgbin0 -> 29913 bytes
-rw-r--r--Article-Update/images/explorer.jpgbin0 -> 23642 bytes
-rw-r--r--Article-Update/images/feature-desc.jpgbin0 -> 33357 bytes
-rw-r--r--Article-Update/images/feature-preview.jpgbin0 -> 49991 bytes
-rw-r--r--Article-Update/images/feature-refs.jpgbin0 -> 37022 bytes
-rw-r--r--Article-Update/images/history.jpgbin0 -> 96358 bytes
-rw-r--r--Article-Update/images/license.jpgbin0 -> 31735 bytes
-rw-r--r--Article-Update/images/one-click2.jpgbin0 -> 81816 bytes
-rw-r--r--Article-Update/images/propsheet.jpgbin0 -> 15098 bytes
-rw-r--r--Article-Update/images/site_obj.gifbin0 -> 162 bytes
-rw-r--r--Article-Update/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Update/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Update/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Update/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Update/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Update/images/url.jpgbin0 -> 58005 bytes
-rw-r--r--Article-Update/keeping-up-to-date.html707
-rw-r--r--Article-Using EMF/Test.familytree19
-rw-r--r--Article-Using EMF/family.mdl583
-rw-r--r--Article-Using EMF/family1.zipbin0 -> 1931 bytes
-rw-r--r--Article-Using EMF/family2.zipbin0 -> 137884 bytes
-rw-r--r--Article-Using EMF/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Using EMF/images/customized.JPGbin0 -> 85585 bytes
-rw-r--r--Article-Using EMF/images/customized.bmpbin0 -> 1213686 bytes
-rw-r--r--Article-Using EMF/images/familytree.JPGbin0 -> 18805 bytes
-rw-r--r--Article-Using EMF/images/labels.JPGbin0 -> 10500 bytes
-rw-r--r--Article-Using EMF/images/labels.bmpbin0 -> 109030 bytes
-rw-r--r--Article-Using EMF/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-Using EMF/images/model.bmpbin0 -> 450522 bytes
-rw-r--r--Article-Using EMF/images/sample.JPGbin0 -> 95228 bytes
-rw-r--r--Article-Using EMF/images/sample.bmpbin0 -> 1449670 bytes
-rw-r--r--Article-Using EMF/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-Using EMF/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-Using EMF/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-Using EMF/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-Using EMF/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-Using EMF/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-Using EMF/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-Using EMF/images/testdata.JPGbin0 -> 83820 bytes
-rw-r--r--Article-Using EMF/images/testdata.bmpbin0 -> 1113334 bytes
-rw-r--r--Article-Using EMF/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Using EMF/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Using EMF/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-Using EMF/using-emf.html504
-rw-r--r--Article-Using Images In Eclipse/Using Images In Eclipse.html355
-rw-r--r--Article-Using Images In Eclipse/history/Using Images In Eclipse_v1.0.htm363
-rw-r--r--Article-VE-Custom-Widget/customwidget.html2724
-rw-r--r--Article-VE-Custom-Widget/customwidgetexample.zipbin0 -> 869556 bytes
-rw-r--r--Article-VE-Custom-Widget/images/CheckOutAsProject.pngbin0 -> 13697 bytes
-rw-r--r--Article-VE-Custom-Widget/images/CreatePluginWizard.pngbin0 -> 19251 bytes
-rw-r--r--Article-VE-Custom-Widget/images/CustomPalette.pngbin0 -> 32059 bytes
-rw-r--r--Article-VE-Custom-Widget/images/CustomPrompterContainer.pngbin0 -> 41902 bytes
-rw-r--r--Article-VE-Custom-Widget/images/CustomTextEditorDialog.pngbin0 -> 78604 bytes
-rw-r--r--Article-VE-Custom-Widget/images/CustomWidget.pngbin0 -> 3606 bytes
-rw-r--r--Article-VE-Custom-Widget/images/CustomWidgetPackage.pngbin0 -> 49671 bytes
-rw-r--r--Article-VE-Custom-Widget/images/EventsMenuAfter.pngbin0 -> 19060 bytes
-rw-r--r--Article-VE-Custom-Widget/images/GraphicalEditPart.pngbin0 -> 7069 bytes
-rw-r--r--Article-VE-Custom-Widget/images/IconsFolder.pngbin0 -> 8455 bytes
-rw-r--r--Article-VE-Custom-Widget/images/JARExport.pngbin0 -> 20347 bytes
-rw-r--r--Article-VE-Custom-Widget/images/JARdiagram.pngbin0 -> 126242 bytes
-rw-r--r--Article-VE-Custom-Widget/images/LaunchConfig.pngbin0 -> 16257 bytes
-rw-r--r--Article-VE-Custom-Widget/images/NewPalette.pngbin0 -> 8151 bytes
-rw-r--r--Article-VE-Custom-Widget/images/OriginalEventsMenu.pngbin0 -> 17561 bytes
-rw-r--r--Article-VE-Custom-Widget/images/OriginalGraphicalEditPart.pngbin0 -> 5996 bytes
-rw-r--r--Article-VE-Custom-Widget/images/OriginalPalette.pngbin0 -> 6685 bytes
-rw-r--r--Article-VE-Custom-Widget/images/OriginalTextProperty.pngbin0 -> 2062 bytes
-rw-r--r--Article-VE-Custom-Widget/images/OriginalTypeProperty.pngbin0 -> 2292 bytes
-rw-r--r--Article-VE-Custom-Widget/images/OverrideFileStructure.pngbin0 -> 13565 bytes
-rw-r--r--Article-VE-Custom-Widget/images/PreReqPlugins.pngbin0 -> 9211 bytes
-rw-r--r--Article-VE-Custom-Widget/images/RepositoriesView.pngbin0 -> 9131 bytes
-rw-r--r--Article-VE-Custom-Widget/images/RuintimeLibraryPluginName.pngbin0 -> 6019 bytes
-rw-r--r--Article-VE-Custom-Widget/images/RuntimeLibraryPluginName.jpgbin0 -> 12875 bytes
-rw-r--r--Article-VE-Custom-Widget/images/TestProjectBuildPath.pngbin0 -> 9323 bytes
-rw-r--r--Article-VE-Custom-Widget/images/TextCurrentValue.pngbin0 -> 2754 bytes
-rw-r--r--Article-VE-Custom-Widget/images/TextPropertyCellEditor.pngbin0 -> 1849 bytes
-rw-r--r--Article-VE-Custom-Widget/images/TextPropertyDisplayed.pngbin0 -> 2196 bytes
-rw-r--r--Article-VE-Custom-Widget/images/TypeCodeGeneration.pngbin0 -> 32670 bytes
-rw-r--r--Article-VE-Custom-Widget/images/TypePropertyCellEditor.pngbin0 -> 3494 bytes
-rw-r--r--Article-VE-Custom-Widget/images/TypePropertyLabelProvider.pngbin0 -> 2397 bytes
-rw-r--r--Article-VE-Custom-Widget/images/custom.gifbin0 -> 582 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/editor_extension.jpgbin0 -> 176281 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/struts-config_1_0.pngbin0 -> 12275 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/struts-config_1_1.pngbin0 -> 18766 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/struts-config_1_2.pngbin0 -> 19341 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/strutsconfig.pngbin0 -> 58540 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/thumb-editor_extension.jpgbin0 -> 111708 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/thumb-struts-config_1_0.pngbin0 -> 4960 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/thumb-struts-config_1_1.pngbin0 -> 7957 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/thumb-struts-config_1_2.pngbin0 -> 8183 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/thumb-strutsconfig.pngbin0 -> 27061 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-WTP-Persisting-EMF/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-WTP-Persisting-EMF/persisting.html475
-rw-r--r--Article-WTP-Persisting-EMF/strutsbox.strutsconfig.zipbin0 -> 337572 bytes
-rw-r--r--Article-Workbench-DND/drag_drop.html620
-rw-r--r--Article-Workbench-DND/gadgetsrc.zipbin0 -> 13411 bytes
-rw-r--r--Article-Workbench-DND/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Workbench-DND/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-Workbench-DND/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget.htm6632
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/AppendixA.htm10017
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/AppendixB.htm198
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/AppendixC.htm313
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/AppendixD.htm317
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/AppendixE.htm1517
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/AppendixE_files/filelist.xml5
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/AppendixE_files/header.htm66
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/default_style.css11
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/filelist.xml14
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/header.htm69
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/image001.pngbin0 -> 581 bytes
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/image002.jpgbin0 -> 1069 bytes
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/image003.pngbin0 -> 894 bytes
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/image004.jpgbin0 -> 2562 bytes
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/image005.pngbin0 -> 4119 bytes
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/image006.jpgbin0 -> 21138 bytes
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/image007.pngbin0 -> 2611 bytes
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/image008.jpgbin0 -> 2930 bytes
-rw-r--r--Article-Writing Your Own Widget/Writing Your Own Widget_files/oledata.msobin0 -> 5120 bytes
-rw-r--r--Article-Your First Plug-in/YourFirstPlugin.html425
-rw-r--r--Article-Your First Plug-in/history/Your First Plug-in.html423
-rw-r--r--Article-small-cup-of-swt/FileDialogMain.java24
-rw-r--r--Article-small-cup-of-swt/HelloWorld.java35
-rw-r--r--Article-small-cup-of-swt/OkButton.java27
-rw-r--r--Article-small-cup-of-swt/SipResize.java28
-rw-r--r--Article-small-cup-of-swt/SmallDialog.java30
-rw-r--r--Article-small-cup-of-swt/SmartMinimize.java22
-rw-r--r--Article-small-cup-of-swt/StylusHold.java28
-rw-r--r--Article-small-cup-of-swt/class_load_j2me_cldc.txt89
-rw-r--r--Article-small-cup-of-swt/class_load_j2se.txt240
-rw-r--r--Article-small-cup-of-swt/images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Article-small-cup-of-swt/images/ant_script.pngbin0 -> 33833 bytes
-rw-r--r--Article-small-cup-of-swt/images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--Article-small-cup-of-swt/images/ppc01.pngbin0 -> 7676 bytes
-rw-r--r--Article-small-cup-of-swt/images/ppc02.pngbin0 -> 3425 bytes
-rw-r--r--Article-small-cup-of-swt/images/ppc03.pngbin0 -> 5004 bytes
-rw-r--r--Article-small-cup-of-swt/images/ppc04.pngbin0 -> 6219 bytes
-rw-r--r--Article-small-cup-of-swt/images/ppc05.pngbin0 -> 3415 bytes
-rw-r--r--Article-small-cup-of-swt/images/ppc06.pngbin0 -> 3491 bytes
-rw-r--r--Article-small-cup-of-swt/images/ppc07.pngbin0 -> 1863 bytes
-rw-r--r--Article-small-cup-of-swt/images/ppc08.pngbin0 -> 1872 bytes
-rw-r--r--Article-small-cup-of-swt/images/profiles.gifbin0 -> 3396 bytes
-rw-r--r--Article-small-cup-of-swt/images/profiles.pngbin0 -> 2752 bytes
-rw-r--r--Article-small-cup-of-swt/images/swtjar.pngbin0 -> 5527 bytes
-rw-r--r--Article-small-cup-of-swt/images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--Article-small-cup-of-swt/images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--Article-small-cup-of-swt/images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--Article-small-cup-of-swt/images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--Article-small-cup-of-swt/images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--Article-small-cup-of-swt/images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--Article-small-cup-of-swt/images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--Article-small-cup-of-swt/images/tip.gifbin0 -> 406 bytes
-rw-r--r--Article-small-cup-of-swt/images/tryit.gifbin0 -> 309 bytes
-rw-r--r--Article-small-cup-of-swt/images/win_only.gifbin0 -> 221 bytes
-rw-r--r--Article-small-cup-of-swt/pocket-PC.html799
-rw-r--r--GettingStartedWithSWT/swt-getting-started.html117
-rw-r--r--GettingStartedWithSWT/swt-style-bits.html1302
-rw-r--r--GettingStartedWithSWT/swt-widget-hierarchy.html800
-rw-r--r--Online Help/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--Online Help/final.jpgbin0 -> 46096 bytes
-rw-r--r--Online Help/final.zipbin0 -> 6894 bytes
-rw-r--r--Online Help/help1.htm470
-rw-r--r--Online Help/initialstructure.zipbin0 -> 6894 bytes
-rw-r--r--Online Help/readme.txt12
-rw-r--r--Online Help/toplevel.jpgbin0 -> 5456 bytes
-rw-r--r--PropertyContribution.html52
-rw-r--r--SolvingTheSoftwareParadox.html296
-rw-r--r--StyledText 1/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--StyledText 1/Image0.gifbin0 -> 1996 bytes
-rw-r--r--StyledText 1/Image1.gifbin0 -> 2010 bytes
-rw-r--r--StyledText 1/Image2.gifbin0 -> 1886 bytes
-rw-r--r--StyledText 1/Image3.gifbin0 -> 2066 bytes
-rw-r--r--StyledText 1/Image4.gifbin0 -> 2019 bytes
-rw-r--r--StyledText 1/Image5.gifbin0 -> 2037 bytes
-rw-r--r--StyledText 1/Image6.gifbin0 -> 2002 bytes
-rw-r--r--StyledText 1/TextChanges.gifbin0 -> 13592 bytes
-rw-r--r--StyledText 1/article1.html957
-rw-r--r--StyledText 2/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--StyledText 2/Image8.gifbin0 -> 7728 bytes
-rw-r--r--StyledText 2/StyledTextContentSpec.java976
-rw-r--r--StyledText 2/TextChanges.gifbin0 -> 13029 bytes
-rw-r--r--StyledText 2/TextUpdate.gifbin0 -> 11618 bytes
-rw-r--r--StyledText 2/article2.html829
-rw-r--r--ToolIntegration/ToolIntegration.html417
-rw-r--r--ToolIntegration/images/currentToolIntegration.gifbin0 -> 58682 bytes
-rw-r--r--ToolIntegration/images/eclipseOverview.gifbin0 -> 84809 bytes
-rw-r--r--ToolIntegration/images/image004.gifbin0 -> 62093 bytes
-rw-r--r--ToolIntegration/images/image007.gifbin0 -> 213 bytes
-rw-r--r--ToolIntegration/images/image008.gifbin0 -> 260 bytes
-rw-r--r--ToolIntegration/images/image009.gifbin0 -> 276 bytes
-rw-r--r--ToolIntegration/images/image010.gifbin0 -> 276 bytes
-rw-r--r--ToolIntegration/images/pressures.gifbin0 -> 119772 bytes
-rw-r--r--ToolIntegration/images/problemSpace.gifbin0 -> 46649 bytes
-rw-r--r--ToolIntegration/images/webTransaction.gifbin0 -> 41119 bytes
-rw-r--r--ToolIntegration/images/workbenchIntegration.gifbin0 -> 68188 bytes
-rw-r--r--article-template.zipbin0 -> 12649 bytes
-rw-r--r--contributing.html127
-rw-r--r--images/Adarrow.gifbin0 -> 857 bytes
-rw-r--r--images/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--images/howto_banner.jpgbin0 -> 9877 bytes
-rw-r--r--images/htmltoolbar.jpgbin0 -> 39205 bytes
-rw-r--r--images/linux_only.gifbin0 -> 174 bytes
-rw-r--r--images/markers.jpgbin0 -> 190691 bytes
-rw-r--r--images/normaltoolbar.jpgbin0 -> 24853 bytes
-rw-r--r--images/note.gifbin0 -> 1014 bytes
-rw-r--r--images/notifiers.gifbin0 -> 7404 bytes
-rw-r--r--images/srctoolbar.jpgbin0 -> 38142 bytes
-rw-r--r--images/tag_1.gifbin0 -> 150 bytes
-rw-r--r--images/tag_2.gifbin0 -> 165 bytes
-rw-r--r--images/tag_3.gifbin0 -> 166 bytes
-rw-r--r--images/tag_4.gifbin0 -> 159 bytes
-rw-r--r--images/tag_5.gifbin0 -> 166 bytes
-rw-r--r--images/tag_6.gifbin0 -> 168 bytes
-rw-r--r--images/tag_7.gifbin0 -> 160 bytes
-rw-r--r--images/tip.gifbin0 -> 406 bytes
-rw-r--r--images/tryit.gifbin0 -> 309 bytes
-rw-r--r--images/win_only.gifbin0 -> 221 bytes
-rw-r--r--index.html21
-rw-r--r--index.php2
-rw-r--r--main.html1015
-rw-r--r--preferences/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--preferences/badwordpreference.jpgbin0 -> 35650 bytes
-rw-r--r--preferences/colorpreference.jpgbin0 -> 33397 bytes
-rw-r--r--preferences/default_style.css11
-rw-r--r--preferences/preferences.htm345
-rw-r--r--preferences/preferences.zipbin0 -> 4575 bytes
-rw-r--r--preferences/readme.txt12
-rw-r--r--preferences/tag_1.gifbin0 -> 150 bytes
-rw-r--r--preferences/tag_2.gifbin0 -> 165 bytes
-rw-r--r--preferences/tag_3.gifbin0 -> 166 bytes
-rw-r--r--preferences/tree.jpgbin0 -> 38331 bytes
-rw-r--r--product-guide/TryIt.gifbin0 -> 309 bytes
-rw-r--r--product-guide/default_style.css12
-rw-r--r--product-guide/final.jpgbin0 -> 153566 bytes
-rw-r--r--product-guide/guide.html854
-rw-r--r--product-guide/idea.jpgbin0 -> 5102 bytes
-rw-r--r--product-guide/linux_only.gifbin0 -> 174 bytes
-rw-r--r--product-guide/tip.gifbin0 -> 406 bytes
-rw-r--r--product-guide/win_only.gifbin0 -> 221 bytes
-rw-r--r--swt-design-2/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--swt-design-2/LeakExample.java.htm130
-rw-r--r--swt-design-2/Sleak.java.htm274
-rw-r--r--swt-design-2/default_style.css11
-rw-r--r--swt-design-2/sleak.1.gifbin0 -> 3479 bytes
-rw-r--r--swt-design-2/sleak.2.gifbin0 -> 2949 bytes
-rw-r--r--swt-design-2/sleak.3.gifbin0 -> 3283 bytes
-rw-r--r--swt-design-2/sleak.4.gifbin0 -> 3388 bytes
-rw-r--r--swt-design-2/sleak.5.gifbin0 -> 3461 bytes
-rw-r--r--swt-design-2/sleak.6.gifbin0 -> 3554 bytes
-rw-r--r--swt-design-2/sleak.7.gifbin0 -> 8657 bytes
-rw-r--r--swt-design-2/sleak.8.gifbin0 -> 3548 bytes
-rw-r--r--swt-design-2/sleak.htm225
-rw-r--r--swt-design-2/swt-design-2.html526
-rw-r--r--update_landing_page.php42
-rw-r--r--using-perspectives/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--using-perspectives/PerspectiveArticle.html822
-rw-r--r--using-perspectives/TestPerspective.jpgbin0 -> 92348 bytes
-rw-r--r--using-perspectives/TestPerspectiveSketch.jpgbin0 -> 83475 bytes
-rw-r--r--using-perspectives/default_style.css11
-rw-r--r--using-perspectives/workbench_decomposed.jpgbin0 -> 66773 bytes
-rw-r--r--viewArticle/Idea.jpgbin0 -> 5102 bytes
-rw-r--r--viewArticle/LabelView.jpgbin0 -> 57258 bytes
-rw-r--r--viewArticle/ListenerView.jpgbin0 -> 68794 bytes
-rw-r--r--viewArticle/ViewArticle2.html1212
-rw-r--r--viewArticle/WordView.jpgbin0 -> 59500 bytes
-rw-r--r--viewArticle/arrow.gifbin0 -> 87 bytes
-rw-r--r--viewArticle/default_style.css11
-rw-r--r--viewArticle/menus.jpgbin0 -> 27564 bytes
-rw-r--r--viewArticle/tag_a.jpgbin0 -> 916 bytes
-rw-r--r--viewArticle/tag_b.jpgbin0 -> 924 bytes
-rw-r--r--viewArticle/tag_c.jpgbin0 -> 913 bytes
-rw-r--r--viewArticle/tag_d.jpgbin0 -> 914 bytes
-rw-r--r--viewArticle/tag_e.jpgbin0 -> 909 bytes
-rw-r--r--viewArticle/tag_f.jpgbin0 -> 893 bytes
-rw-r--r--viewArticle/tag_g.jpgbin0 -> 923 bytes
-rw-r--r--viewArticle/viewArticleSrc.zipbin0 -> 240382 bytes
1317 files changed, 98557 insertions, 43 deletions
diff --git a/Article-EditorContributor/EditorContributor.html b/Article-EditorContributor/EditorContributor.html
new file mode 100644
index 0000000..608435f
--- /dev/null
+++ b/Article-EditorContributor/EditorContributor.html
@@ -0,0 +1,235 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="Author" content="Dejan Glozic">
+<meta name="GENERATOR" content="Mozilla/4.75 [en] (Windows NT 5.0; U) [Netscape]">
+<title>Writing Error Report</title>
+</head>
+<body>
+&nbsp;
+<table BORDER=0 CELLSPACING=0 CELLPADDING=2 WIDTH="100%" >
+ <tr>
+ <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica"><font color="#FFFFFF">&nbsp;Eclipse
+ Corner Article</font></font></b></td>
+ </tr>
+</table>
+<h1> <img SRC="../images/Idea.jpg" height=86 width=120 align=CENTER></h1>
+<center>
+ <h1> Editor Contributors - A Distinct Species</h1>
+</center>
+<center>
+ <h3> Why are Eclipse desktop editors using a distinct contribution mechanism
+ instead of simply doing it directly from editors</h3>
+</center>
+<blockquote><b>Summary</b> <br>
+ Eclipse platform desktop offers various ways a plugin can contribute to menus
+ and tool bars. The most natural way for views is to contribute directly (if
+ you own the view, that is). However, editors are somewhat special - their contributors
+ are registered alongside editors and contribution from editor instances is not
+ allowed. This article explains why the difference and how editor contributors
+ prevent renegade runtime footprint and improve user experience. We will also
+ take a look at handling editor contributors in multi-page editors.</blockquote>
+<b>By <a href="mailto:dejan@ca.ibm.com">Dejan Glozic</a></b>
+<p>
+<hr WIDTH="100%">
+<br>
+One of the primary mechanisms of interaction with an Eclipse platform application
+is by performing actions in the given context. Whether you use menus, tool bars,
+accelerator keys etc. to perform an action is less important. Consequently, one
+of the most important considerations for Eclipse plugins is how to expose these
+actions to the user.
+<p>A standalone application developer has a relatively easy task since he owns
+ all of the action vectors (menu bars, tool bars, pop-up menus etc.). A plugin
+ developer must view its task as a contribution to the whole. Its contribution
+ will 'rub elbows' with those from other plugins, and seamless integration becomes
+ very important.
+<p>Desktop integration of actions is relatively easy for view developers. Eclipse
+ views are fairly encapsulated desktop parts. They have a local tool bar and
+ a pull-down menu. Because of this encapsulation, adding a view to the desktop
+ is a relatively easy affair.
+<p>Content editor is a completely different animal. Editors normally require a
+ large number of actions that are applicable in their context. Embedding these
+ actions into the desktop part is not possible in all but a very few simple cases.
+ Instead, editors add their actions to the shared desktop areas: the main menu
+ and tool bars. This creates a few problems. There can be potentially many editors
+ opened at once. They cannot all add their menus and tool bars into the shared
+ area - it would be a disaster. It would not be right either, because only one
+ editor can be active at a time. A context switching mechanism is needed to make
+ sure that only actions of the active editor are visible at any given point in
+ time.
+<p>Context switching ensures that visibility of the editor and its actions in
+ the desktop's shared areas are in sync. This requirement cannot be left to editor
+ developers - it is too important. Instead, editors are asked to create a contribution
+ and this contribution is used to add and remove actions on active editor switching.
+<h3> Contribution Memento</h3>
+The desktop implements context switching by using a feature of JFace contribution
+managers called <b>modification bracketing</b>. If you add actions into a contribution
+manager in its normal state, they will end up in its managed shared area of the
+desktop. However, it is possible to go into <b>recording mode</b> by calling a
+method <b>beginModification</b>. From that moment on, all contributions made to
+this manager are going into a separate record called <b>contribution memento</b>.
+Once we are done contributing, we call <b>endModification</b>. This method will
+restore the normal state of the manager and also return an <tt>ContributionMemento</tt>
+object. We can use this object to activate or deactivate it when needed. Activating
+a memento means adding all of the recorded actions to the originating manager.
+Similarly, deactivation of the memento removes the actions.
+<p>Usage of mementos is transparent to editor developers. Eclipse desktop employs
+ mementos to implement context switching, and ISVs are only required to do the
+ contribution part. The only thing for developers to remember is that some kind
+ of recording takes place, and that it is done on editor creation. Editors will
+ not be able to modify their contribution afterwards - it will simply be switched
+ in and out, as shown in Figure 1. <br>
+ &nbsp; <br>
+ &nbsp;
+<center>
+ <table BORDER=0 CELLSPACING=5 CELLPADDING=0 WIDTH="48%" >
+ <tr>
+ <td ALIGN=CENTER VALIGN=CENTER><img SRC="images/normaltoolbar.jpg" height=132 width=615></td>
+ </tr>
+ <tr>
+ <td ALIGN=CENTER VALIGN=CENTER><b><font size=-1>(a)&nbsp;</font></b></td>
+ </tr>
+ <tr>
+ <td ALIGN=CENTER VALIGN=CENTER><img SRC="images/htmltoolbar.jpg" height=132 width=615></td>
+ </tr>
+ <tr>
+ <td ALIGN=CENTER VALIGN=CENTER><b><font size=-1>(b)</font></b></td>
+ </tr>
+ <tr>
+ <td><b><font size=-1>Figure 1: Eclipse desktop menu and tool bar with no
+ editors (a) and with HTML editor opened (b). Note how there are more menus
+ and buttons in picture (b). These additions are coming from the contribution
+ associated with the editor.</font></b></td>
+ </tr>
+ </table>
+</center>
+<h3> The problem of flashing and run-time memory waste</h3>
+If you are writing a desktop view, contributing to the local tool bar is fairly
+simple - you simply ask for the local tool bar manager and add your actions. Similar
+scenario could be envisioned for contributing from the content editors, but it
+is not used, and for a reason. Consider the following: desktop views are unique.
+There cannot be multiple instances of the same view showing up in the desktop
+(if you try to reopen a view, the currently opened instance simply pops up and
+regains focus). However, there can be many instances of the same editor type opened
+at the same time, one for each file. If we contribute actions from the editor
+instance itself, that would mean a huge waste of time and memory.
+<p>For example: if we open 10 HTML files with a Web Tooling editor, and it has
+ 40 actions to contribute, we will have 400 action instances in memory. Only
+ 10% of these instances will be used at any point in time because only one of
+ these editors can be active. The remaining 90% will be switched out.
+<p>There is also a problem of menu and tool bar updates. In a naive implementation,
+ every editor switch would mean context switching for these shared areas: actions
+ of the deactivating editor will be removed, while those of the activating editor
+ will be added. But switching between editors of the same type means that we
+ are removing and adding instances of the same actions. Nothing will change in
+ the desktop except the unavoidable pause and flashing.
+<h3> The Eclipse solution</h3>
+The Eclipse desktop solution for this problem is to move editor contribution from
+editor <i>instances</i> to editor <i>types</i>. The desktop extension point for
+registering new editors accepts not only the Java class name for the editor, but
+also an optional class name for the <b>editor contributor</b>:
+<p><tt>interface IEditorActionBarContributor extends IActionBarContributor {</tt>
+ <br>
+ <tt>&nbsp;&nbsp; public void editorChanged(IEditorPart editor);</tt> <br>
+ <tt>}</tt>
+<p>This contributor extends action bar contributor interface and adds a method
+ to inform you about the editor change. This method is called only when editors
+ of your editor type are switched, so you can safely cast it into your editor
+ class. The implementors of this interface would use its required methods (<tt>contributeToMenu</tt>,
+ <tt>contributeToToolBar</tt> etc.) to add actions, submenus etc. in the usual
+ way. The key difference here is that these actions must be designed without
+ any specific editor instance in mind. They have to work on the currently active
+ instance, which means that they need to recalculate their enable state every
+ time there is editor change.
+<p>When a file is opened for editing, and the editor instance is the first of
+ that editor type to be opened, the contributor will be created as well. The
+ contributor will create a memento and keep it. When editors are switched, it
+ will use the memento to switch actions in or out. When another editor instance
+ of the same type is opened, no new actions will be created. The running contributor
+ will call <tt>editorChanged</tt> to allow actions to update. Contributor and
+ its actions will be removed and disposed only when the last instance of this
+ editor type is closed.
+<p>The key difference here is that context switching will occur only when two
+ editors of the <i>different</i> type are switched. On switching editors of the
+ same type, only <tt>editorChanged</tt> will be called in the contributor. This
+ means that editor changes will be smooth, with no flashes and pauses.
+<h3> Multi-page editors</h3>
+The situation complicates somewhat if the content editor if of a multi-page variety
+(for example, Web tooling HTML editor with its Design, Source and Preview pages).
+In this case, actions need to update their availability not only on an editor-to-editor
+basis, but also on page switches within the same editor, as shown in Figure 2.
+Since editor instance do not have access to editor actions (actions are normally
+created as fields of the class that implements contributor interface), the following
+solution may work well.
+<p>First, create a page listener interface:
+<blockquote><tt>interface IEditorPageListener {</tt> <br>
+ <tt>&nbsp;&nbsp; public void pageChanged(WorkbookPage page);</tt> <br>
+ <tt>}</tt></blockquote>
+In your multi-page editor class, add two methods to register the listener:
+<blockquote><tt>public void addEditorPageListener(IEditorPageListener listener);</tt>
+ <br>
+ <tt>public void removeEditorPageListener(IEditorPageListener listener);</tt></blockquote>
+When page within the editor changes, notify the listeners by calling <tt>pageChanged</tt>
+with the newly active page.
+<p>In the implementation of editor contributor, connect on each editor switch:
+<p><tt>public MultiPageContributor implements IEditorActionBarContributor,</tt>
+ <br>
+ <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ IEditorPageListener {</tt> <br>
+ <tt>&nbsp;&nbsp; MyMultiPageEditor currentEditor=null;</tt><tt></tt>
+<p><tt>&nbsp;&nbsp; public void editorChanged(IEditorPart part) {</tt> <br>
+ <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyMyltiPageEditor editor = (MyMultiPageEditor)part;</tt>
+ <br>
+ <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (currentEditor!=null) currentEditor.removeEditorPageListener(this);</tt>
+ <br>
+ <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentEditor = editor;</tt> <br>
+ <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentEditor.addEditorPageListener(this);</tt>
+ <br>
+ <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; updateActions();</tt> <br>
+ <tt>&nbsp;&nbsp; }</tt> <br>
+ <tt>&nbsp;&nbsp; public void pageChanged(WorkbookPage page) {</tt> <br>
+ <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; updateActions(page);</tt> <br>
+ <tt>&nbsp;&nbsp; }</tt> <br>
+ <tt>}</tt>
+<p>The behavior of this class is straightforward: when editor becomes active,
+ the contributor disconnects from the old editor and connects to the new one.
+ While the current editor is active, page changes within it will cause the contributor
+ to update the action state. The two overloaded methods for updating actions
+ not shown here simply update the state of the actions according to the state
+ of the current editor and the currently selected page in the editor. <br>
+ &nbsp; <br>
+ &nbsp; <br>
+ &nbsp;
+<center>
+ <table BORDER=0 CELLSPACING=5 CELLPADDING=0 WIDTH="48%" >
+ <tr>
+ <td ALIGN=CENTER VALIGN=CENTER><img SRC="images/htmltoolbar.jpg" BORDER=0 height=132 width=615></td>
+ </tr>
+ <tr>
+ <td ALIGN=CENTER VALIGN=CENTER><b><font size=-1>(a)&nbsp;</font></b></td>
+ </tr>
+ <tr>
+ <td ALIGN=CENTER VALIGN=CENTER><img SRC="images/srctoolbar.jpg" height=132 width=615></td>
+ </tr>
+ <tr>
+ <td ALIGN=CENTER VALIGN=CENTER><b><font size=-1>(b)</font></b></td>
+ </tr>
+ <tr>
+ <td><b><font size=-1>Figure 2: Eclipse desktop menu and tool bar for the
+ Source (a) and Design view&nbsp; (b) of the HTML editor. The same actions
+ are present for&nbsp; both pages, but some of them are disabled for the
+ Source view.</font></b></td>
+ </tr>
+ </table>
+</center>
+<br>
+&nbsp;
+<h3> Conclusion</h3>
+This article has shown how contribution to menus and tool bars is 'special' in
+Eclipse desktop. We described the use of JFace contribution mementos. The article
+has also shown how the problem of tool bar flashing and action duplication is
+solved by removing contributors from editor instances. Finally, a tip on handling
+multi-page editors is presented.
+</body>
+</html>
diff --git a/Article-EditorContributor/images/Adarrow.gif b/Article-EditorContributor/images/Adarrow.gif
new file mode 100644
index 0000000..1848247
--- /dev/null
+++ b/Article-EditorContributor/images/Adarrow.gif
Binary files differ
diff --git a/Article-EditorContributor/images/Idea.jpg b/Article-EditorContributor/images/Idea.jpg
new file mode 100644
index 0000000..119ce70
--- /dev/null
+++ b/Article-EditorContributor/images/Idea.jpg
Binary files differ
diff --git a/Article-EditorContributor/images/articles.gif b/Article-EditorContributor/images/articles.gif
new file mode 100644
index 0000000..47d972c
--- /dev/null
+++ b/Article-EditorContributor/images/articles.gif
Binary files differ
diff --git a/Article-EditorContributor/images/howto_banner.jpg b/Article-EditorContributor/images/howto_banner.jpg
new file mode 100644
index 0000000..f2e2d42
--- /dev/null
+++ b/Article-EditorContributor/images/howto_banner.jpg
Binary files differ
diff --git a/Article-EditorContributor/images/htmltoolbar.jpg b/Article-EditorContributor/images/htmltoolbar.jpg
new file mode 100644
index 0000000..86b105c
--- /dev/null
+++ b/Article-EditorContributor/images/htmltoolbar.jpg
Binary files differ
diff --git a/Article-EditorContributor/images/linux_only.gif b/Article-EditorContributor/images/linux_only.gif
new file mode 100644
index 0000000..7c135cf
--- /dev/null
+++ b/Article-EditorContributor/images/linux_only.gif
Binary files differ
diff --git a/Article-EditorContributor/images/markers.jpg b/Article-EditorContributor/images/markers.jpg
new file mode 100644
index 0000000..85195e6
--- /dev/null
+++ b/Article-EditorContributor/images/markers.jpg
Binary files differ
diff --git a/Article-EditorContributor/images/normaltoolbar.jpg b/Article-EditorContributor/images/normaltoolbar.jpg
new file mode 100644
index 0000000..b05173c
--- /dev/null
+++ b/Article-EditorContributor/images/normaltoolbar.jpg
Binary files differ
diff --git a/Article-EditorContributor/images/note.gif b/Article-EditorContributor/images/note.gif
new file mode 100644
index 0000000..f6260db
--- /dev/null
+++ b/Article-EditorContributor/images/note.gif
Binary files differ
diff --git a/Article-EditorContributor/images/notifiers.gif b/Article-EditorContributor/images/notifiers.gif
new file mode 100644
index 0000000..aefc75d
--- /dev/null
+++ b/Article-EditorContributor/images/notifiers.gif
Binary files differ
diff --git a/Article-EditorContributor/images/srctoolbar.jpg b/Article-EditorContributor/images/srctoolbar.jpg
new file mode 100644
index 0000000..2042b12
--- /dev/null
+++ b/Article-EditorContributor/images/srctoolbar.jpg
Binary files differ
diff --git a/Article-EditorContributor/images/tag_1.gif b/Article-EditorContributor/images/tag_1.gif
new file mode 100644
index 0000000..4859d6f
--- /dev/null
+++ b/Article-EditorContributor/images/tag_1.gif
Binary files differ
diff --git a/Article-EditorContributor/images/tag_2.gif b/Article-EditorContributor/images/tag_2.gif
new file mode 100644
index 0000000..5ea43dc
--- /dev/null
+++ b/Article-EditorContributor/images/tag_2.gif
Binary files differ
diff --git a/Article-EditorContributor/images/tag_3.gif b/Article-EditorContributor/images/tag_3.gif
new file mode 100644
index 0000000..a69b68e
--- /dev/null
+++ b/Article-EditorContributor/images/tag_3.gif
Binary files differ
diff --git a/Article-EditorContributor/images/tag_4.gif b/Article-EditorContributor/images/tag_4.gif
new file mode 100644
index 0000000..a1ad63f
--- /dev/null
+++ b/Article-EditorContributor/images/tag_4.gif
Binary files differ
diff --git a/Article-EditorContributor/images/tag_5.gif b/Article-EditorContributor/images/tag_5.gif
new file mode 100644
index 0000000..d86a748
--- /dev/null
+++ b/Article-EditorContributor/images/tag_5.gif
Binary files differ
diff --git a/Article-EditorContributor/images/tag_6.gif b/Article-EditorContributor/images/tag_6.gif
new file mode 100644
index 0000000..b9eb4ec
--- /dev/null
+++ b/Article-EditorContributor/images/tag_6.gif
Binary files differ
diff --git a/Article-EditorContributor/images/tag_7.gif b/Article-EditorContributor/images/tag_7.gif
new file mode 100644
index 0000000..5f0e8fa
--- /dev/null
+++ b/Article-EditorContributor/images/tag_7.gif
Binary files differ
diff --git a/Article-EditorContributor/images/tip.gif b/Article-EditorContributor/images/tip.gif
new file mode 100644
index 0000000..77b2451
--- /dev/null
+++ b/Article-EditorContributor/images/tip.gif
Binary files differ
diff --git a/Article-EditorContributor/images/tryit.gif b/Article-EditorContributor/images/tryit.gif
new file mode 100644
index 0000000..f4927a4
--- /dev/null
+++ b/Article-EditorContributor/images/tryit.gif
Binary files differ
diff --git a/Article-EditorContributor/images/win_only.gif b/Article-EditorContributor/images/win_only.gif
new file mode 100644
index 0000000..895f9ca
--- /dev/null
+++ b/Article-EditorContributor/images/win_only.gif
Binary files differ
diff --git a/Article-EditorContributor/images/write.png b/Article-EditorContributor/images/write.png
new file mode 100644
index 0000000..1e68ddd
--- /dev/null
+++ b/Article-EditorContributor/images/write.png
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/default_style.css b/Article-Folding-in-Eclipse-Text-Editors/default_style.css
new file mode 100644
index 0000000..d725483
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/default_style.css
@@ -0,0 +1,11 @@
+p, table, td, th { font-family: arial, helvetica, geneva; font-size: 10pt}
+pre { font-family: "Courier New", Courier, mono; font-size: 10pt}
+h2 { font-family: arial, helvetica, geneva; font-size: 18pt; font-weight: bold ; line-height: 14px}
+code { font-family: "Courier New", Courier, mono; font-size: 10pt}
+sup { font-family: arial,helvetica,geneva; font-size: 10px}
+h3 { font-family: arial, helvetica, geneva; font-size: 14pt; font-weight: bold}
+li { font-family: arial, helvetica, geneva; font-size: 10pt}
+h1 { font-family: arial, helvetica, geneva; font-size: 28px; font-weight: bold}
+body { font-family: arial, helvetica, geneva; font-size: 10pt; clip: rect( ); margin-top: 5mm; margin-left: 3mm}
+.indextop { font-size: x-large;; font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold}
+.indexsub { font-size: xx-small;; font-family: Arial, Helvetica, sans-serif; color: #8080FF}
diff --git a/Article-Folding-in-Eclipse-Text-Editors/folding.html b/Article-Folding-in-Eclipse-Text-Editors/folding.html
new file mode 100644
index 0000000..6439a0a
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/folding.html
@@ -0,0 +1,395 @@
+<html>
+
+<head>
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
+<title>Folding in Eclipse Text Editors</title>
+<link rel="stylesheet" href="default_style.css">
+</head>
+
+<body LINK="#0000ff" VLINK="#800080">
+<div align="right">&nbsp; <font face="Times New Roman, Times, serif" size="2">Copyright
+ &copy; 2005 Prashant Deva</font>
+ <table border=0 cellspacing=0 cellpadding=2 width="100%">
+ <tr>
+ <td align=LEFT valign=TOP colspan="2" bgcolor="#0080C0"><b><font face="Arial,Helvetica"><font color="#FFFFFF">&nbsp;Eclipse
+ Corner Article</font></font></b></td>
+ </tr>
+ </table>
+</div>
+<div align="left">
+ <h1><img src="images/Idea.jpg" height=86 width=120 align=CENTER></h1>
+</div>
+<p>&nbsp;</p>
+
+<h1 ALIGN="CENTER">Folding in Eclipse Text Editors</h1>
+
+<blockquote>
+<b>Summary</b>
+
+<br>
+ Starting with release 3.0, Eclipse allows folding in its text editor. In this
+ article, I explain the new projection infrastructure introduced in
+ the JFace Text framework
+ and show how to extend the XML Editor example provided
+ with Eclipse to allow folding of text.
+ <p><b> By Prashant Deva</b> (<a href="mailto:prashant.deva@gmail.com">prashant.deva@gmail.com</a>)<br>
+ March 11, 2005</p>
+</blockquote>
+
+<hr width="100%">
+<p>Starting with Eclipse 3.0 the JFace Text framework has been extended with a
+ feature to allow for collapsing and expanding of text. This can be noticed in
+ the JDT text editor, which allows you to fold individual methods and classes.
+ You can implement folding in your plug-in too, to allow the users to fold text
+ according the structure of your plug-in's documents.</p>
+<p>You will notice that 2 new packages have been added to the framework: </p>
+<ul>
+ <li><b>org.eclipse.jface.text.projection</b><br>
+ Implements the infrastructure for folding in a UI independent manner. <br>
+ This package resides in the plug-in <code>org.eclipse.text</code>.</li>
+ <li><b>org.eclipse.jface.text.source.projection</b><br>
+ Uses the class in <code>org.eclipse.jface.text.projection</code> to implement
+ folding in a UI dependent manner.<br>
+ This package resides in the plug-in <code>org.eclipse.jface.text</code>. </li>
+</ul>
+<h2>Basic Concept</h2>
+<p>Now let's look at the basic idea in the framework that allows it to just show portions
+ of the actual text. Although these concepts have been in the framework
+ since 2.1, a whole new implementation was added in 3.0 to support the additional
+ requirements of text folding.</p>
+<p><img src="images/withoutFolding.png" width="284" height="172"> &nbsp;&nbsp;&nbsp;&nbsp;<img src="images/withFolding.png" width="364" height="174"></p>
+<p>As you can see in the figure (a) above, without folding things were very simple.
+ We had a document to hold the text and a corresponding view to provide the UI
+ for the text. Now things are a little bit more complicated. We have a <strong>Master
+ Document</strong>, which is like the document we used to use previously.
+ It contains the entire text. However, there is also an additional <strong>Projection
+ Document</strong> attached to a Master Document. The contents of a projection
+ document are a subset of the contents of the Master Document. In other words,
+ the content of a projection document consists of portions of the Master Document.</p>
+<p> As you probabably guessed, when you collapse the text in the editor you see
+ the contents of a projection document containing only the expanded sections.</p>
+ <h2>Behind the scenes</h2>
+<h4>UI Independent Infrastructure </h4>
+<p>Now let’s take a look at the <code>org.eclipse.jface.text.projection</code> package.
+ Keep in mind that you don't actually have to use this package in order to implement
+ folding in your text editor. The following description is just
+ to help you understand the concepts behind the folding infrastructure.<br>
+ <br>
+ The classes we need to concentrate on are:
+<ul>
+ <li><code>ProjectionDocument</code>: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Represents
+ a portion of the content of a Master Document.</li>
+ <li><code>ProjectionDocumentEvent</code>: &nbsp;&nbsp;&nbsp;&nbsp;The event object
+ sent out by ProjectionDocument</li>
+ <li><code>ProjectionDocumentManager</code>: Maintains the association between
+ a Master Document and its Projection Documents.</li>
+ </ul>
+<p>The rest of the classes in the package are for internal use only and we need
+ not bother with them.</p>
+<p>The class <code>ProjectionDocumentManager</code> acts as glue between the master
+ document and its child projection documents, connecting them together. Thus
+ any change made to the projection document causes a corresponding change
+ to the master document and vice versa.</p>
+<p>Here is an example of using ProjectionDocumentManager:</p>
+
+<pre> Document masterDocument = <font color="#0000FF">new</font> Document();
+ ProjectionDocumentManager manager = <font color="#0000FF">new</font> ProjectionDocumentManager();
+<img src="images/tag_1.gif" CENTER>ProjectionDocument projectionDocument = (ProjectionDocument)
+ manager.createSlaveDocument(masterDocument);
+</pre>
+<p>In the above example we first create a <strong>Master Document</strong> and
+ then create a <strong>Projection Document</strong> off of it by using the <code>ProjectionDocumentManager</code>.
+ Instances of the class <code>ProjectionDocument</code>
+ (<img src="images/tag_1.gif" width="24" height="13">)
+ should be created only
+ by using the ‘factory method’ <code>createSlaveDocument()</code> of <code>ProjectionDocumentManager</code>
+ and not instantiated through its constructor. </p>
+<p>A Projection Document has two methods to define its content from the master
+ document:</p>
+<ul>
+ <li><code><font color="#0000FF">public void</font> addMasterDocumentRange(<font color="#0000FF">int</font>
+ offsetInMasterDocument,<font color="#0000FF">int</font> lengthInMasterDocument)</code>
+ <br>
+ Adds a range of text from the Master Document to the Projection Document.
+ <br>&nbsp;</li>
+ <li> <code><font color="#0000FF">public void</font> removeMasterDocumentRange(<font color="#0000FF">int</font>
+ offsetInMasterDocument,<font color="#0000FF">int</font> lengthInMasterDocument)</code><br>
+ Removes a range of text corresponding to the Master Document from the Projection
+ Document.</li>
+</ul>
+<p>Adding more to the previous lines of code: </p>
+<pre>
+masterDocument.set("one two");
+
+<font color="#009900">//removes "one t" from projection document</font>
+projectionDocument.removeMasterDocumentRange(0,5);
+
+<font color="#009900">//adds "ne " to projection document</font>
+projectionDocument.addMasterDocumentRange(1,3);
+
+System.out.println(masterDocument.get()); <font color="#009900">//prints 'one two'</font>
+System.out.println(projectionDocument.get());<font color="#009900">//prints 'ne wo'</font>
+</pre>
+<p>Above, we set the contents of the master document to a string.
+ Doing so
+ automatically sets the contents of the projection document to the same value. Then
+ we modify the projection document to contain only certain portions of the master
+ document. Finally we output the contents of both the documents and see that
+ the portion of master document which we removed from the projection document
+ is not printed out but the contents of the master document remain the same.</p>
+<h2>The Stage</h2>
+<h4>UI Dependent Infrastructure</h4>
+<p>To actually implement folding in your editor, you don't really need to be concerned
+ with the details above.
+ The Eclipse developers have provided a nice package
+ named <code><strong>org.eclipse.jface.text.source.projection</strong></code>
+ that takes care of all the details and makes your job far easier.</p>
+<p>The centerpiece of this package is the <code>ProjectionViewer</code> class,
+ which you must use in your plug-in instead of the usual <code>TextViewer</code>
+ class, to implement folding. A <code>ProjectionViewer</code> internally uses
+ a <code>ProjectionDocumentManager</code> to manage the display of Projection
+ Documents, so we don't have to worry about that. It implements the <code>ITextViewerExtension5</code>
+ interface which is a central part of the UI dependent infrastructure. </p>
+<p><code>ITextViewerExtension5</code> introduces the concept of
+ <em>widget coordinates</em> and <em>model coordinates</em>.
+ A widget coordinate corresponds
+ to a position on the text viewer while a model coordinate corresponds to a position
+ on the document. A widget range always has a corresponding model range which
+ maps to the viewer’s document, while on the other hand a model range can be
+ either ‘exposed’ or ‘unexposed’. An exposed model range is visible on the viewer
+ and can thus be mapped to a widget range. Thus when you expand the text in the
+ viewer, that model range is ‘exposed’ and vice versa. <code>ITextViewerExtension5</code>
+ contains methods to do the conversion from widget to model coordinates and vice
+ versa, and to expose model ranges.</p>
+<h4>Projection Support</h4>
+<p>Another important class in this package is <code>ProjectionSupport</code>.
+ This class controls the display and configuration of all the UI elements related
+ to folding, for example, the painting of those elipsis icons when
+ you collapse a region, and the vertical column that contains the triangle icons
+ to expand/collapse text. A <code>ProjectionSupport</code> instance needs to be installed
+ on a viewer. The XML Editor example shown <a href="#projectionSupport">below</a> demonstrates how to do this
+ in code.</p>
+<p><code>ProjectionSupport</code>
+ allows you to specify <em>summarizable annotation types</em>. Basically,
+ these are the annotations that will appear in the vertical column on the left
+ when you fold the text that contains them. For example, JDT specifies the ‘error’
+ and ‘warning’ annotation types as summarizable, so that when you fold the text
+ that contains a warning or an error, its icon appears on the vertical column
+ besides the folding arrow, as shown below.</p>
+<p><img src="images/annotationSummary.png" width="282" height="129"></p>
+<p>Here is how it is implemented:</p>
+<pre>fProjectionSupport.addSummarizableAnnotationType(
+ "org.eclipse.ui.workbench.texteditor.error");
+fProjectionSupport.addSummarizableAnnotationType(
+ "org.eclipse.ui.workbench.texteditor.warning");
+</pre>
+<p>The <code>setHoverControlCreator()</code> method
+ allows you to set up a hover control to display the collapsed text
+ in a tooltip style box when the use moves the cursor over the arrow.
+ For example:</p>
+<p><img src="images/hover.png" width="223" height="136"></p>
+<p>The constructor takes an <code>IInformationControlCreator</code> as the argument. You usually
+ create an anonymous class here. Here is how JDT does it: </p>
+<pre>fProjectionSupport.setHoverControlCreator(new IInformationControlCreator() {
+ <font color="#0000FF">public</font> IInformationControl createInformationControl(Shell shell) {
+ <font color="#0000FF">return new</font> CustomSourceInformationControl(shell, IDocument.DEFAULT_CONTENT_TYPE);
+ }
+});
+</pre>
+<h4>Projection Annotations</h4>
+<p>To enable folding, we have to specify which regions of the text are collapsible.
+ We do this by
+ calling <code>addAnnotation()</code>
+ adding <code>ProjectionAnnotations</code> to the ProjectionViewer's
+ <code>ProjectionAnnotationModel</code>. The position allows the annotation to
+ be attached to certain text in the editor. </p>
+
+<p>The methods of ProjectionAnnotationModel are pretty self-explanatory: </p>
+<pre><font color="#0000FF">class</font> ProjectionAnnotationModel{
+
+ <font color="#0000FF"> public void</font> collapse(Annotation annotation)
+ <font color="#0000FF"> public void</font> expand(Annotation annotation)
+ <font color="#0000FF"> public boolean</font> expandAll(int offset,int length)
+
+ <font color="#0000FF"> public void</font> toggleExpansionState(Annotation annotation)
+
+ <font color="#0000FF"> public void</font> modifyAnnotations(Annotation[] deletions,Map additions,
+ Annotation[] modifications)
+}
+</pre>
+<p>These methods toggle the annotations to expand/collapse states.
+ The only method which may be confusing is: <code>modifyAnnotations()</code>.
+ This basically does several deletions, additions, and modifications at once.
+ The additions
+ parameter is a Map with Annotation as the key and Position as the value. Executing
+ the method generates a single change event rather than a series of them when
+ you would add and remove annotations one after the other.
+</p>
+<p>A <code>ProjectionAnnotation</code> has the following methods to collapse/expands
+ the text region it is associated with:</p>
+<pre> <font color="#0000FF">public void</font> markCollapsed() <font color="#009933"> //marks the annotation as collapsed</font>
+ <font color="#0000FF">public void</font> markExpanded() <font color="#009933">//marks the annotation as expanded</font>
+ <font color="#0000FF">public boolean</font> isCollapsed() <font color="#009933">//tells whether the annotation is collapsed or expanded</font>
+</pre>
+<p>Thus, when you are working in JDT and you click the arrow on the left side
+ column of the text to collapse it, the method <code>isCollapsed()</code> is
+ called to check whether the text is collapsed or not and then
+ <code>markCollapsed()</code> is called
+ if <code>isCollapsed()</code> returns false. For example,</p>
+<pre> <font color="#0000FF">if</font>(!annotation.isCollapsed())
+ annotation.markCollapsed();
+</pre>
+<p><img src="images/note.gif"> Manipulating ProjectionAnnotations is the only
+ supported way to control folding. Even if you were to get a hold of a Projection
+ Document, its projection behavior should never be manipulated directly. </p>
+<h4>Painting the Annotations...</h4>
+<p>Folding in the editor would be quite useless without the user interface
+ that allowed us to collapse and expand the text.
+ Here's what it looks like in the editor:</p>
+<p><img src="images/projectionAnnotation.png" width="226" height="214"></p>
+<p>ProjectionAnnotation has a method which actually paints those triangles you see
+ on the left.</p>
+<p><code><font color="#0000FF">public void</font> paint(GC gc, Canvas canvas,
+ Rectangle rectangle)</code></p>
+<p>You can override this method in your plug-in if you want to draw something other
+ than an triangle on the left side, for example a plus/minus sign.</p>
+<p>There is one more method you should know about:</p>
+<p><code><font color="#0000FF">public void</font> setRangeIndication(<font color="#0000FF">boolean</font>
+ rangeIndication)</code></p>
+<p>A <em>range indication</em>
+ is that line you see when you move your cursor to an triangle indicating
+ that the text is expanded. The line signifies the range of
+ text that will be collapsed when you click the triangle, and thus the name.
+ Passing true or false to this method controls whether
+ that line is drawn or not.</p>
+
+<h2>The Show</h2>
+<h4>XML Editor plug-in</h4>
+<p>I can hear you saying “Yeah, all this is fine, but how do I actually use this
+ stuff in my plug-in?” Well to show you how to do that I will walk you through
+ a little example. We will extend the XML editor plug-in example provided with
+ Eclipse to allow folding of XML elements. My aim is just to demonstrate the
+ basics of implementing folding here, so I have tried to keep the code as simple
+ as possible. If you want to add any advanced functionality you should be able
+ to do so yourself by now (hopefully) ;-) </p>
+<p>Let's look at the steps involved in supporting folding.
+ Note that all the methods shown below are defined in the class
+ <code>XMLEditor</code> which extends the <code>TextEditor</code> class.</p>
+
+
+<ol>
+ <li>Override <code>createPartControl </code> method of <code>TextEditor</code>
+ to configure and install <code>ProjectionSupport</code></li>
+ <li>Override <code>createSourceViewer</code> method of <code>AbstractTextEditor</code>
+ to return a <code>ProjectionViewer</code></li>
+ <li>Provide some functionality to define collapsible regions</li>
+ </ol>
+ Now lets see how to implement this in our plug-in.
+<p><img src="images/tryit.gif" width="61" height="13">Create a new Plug-in project.
+ At the end of the Project Wizard there will be an option to Create a
+ plug-in using one of the templates. Check it and select Plug-in with an editor.
+ This will create a plug-in with an editor for XML files. Now we will extend
+ this editor to allow the folding of XML elements.</p>
+<p><strong>1)</strong> First, we override the <code> createPartControl</code>
+ method of the <code>TextEditor</code> class. To keep things simple
+ I haven't provided any code for summarizable annotation types or hover controls,
+ but you are free to do so in your own plug-in.</p>
+<a name="projectionSupport"></a><pre><font color="#0000FF">public void</font> createPartControl(Composite parent)
+{
+ <font color="#0000FF">super</font>.createPartControl(parent);
+ ProjectionViewer viewer =(ProjectionViewer)getSourceViewer();
+
+ projectionSupport = new ProjectionSupport(viewer,getAnnotationAccess(),getSharedColors());
+ projectionSupport.install();
+
+ <font color="#009933">//turn projection mode on</font>
+ viewer.doOperation(ProjectionViewer.TOGGLE);
+
+ annotationModel = viewer.getProjectionAnnotationModel();
+
+}</pre>
+<p><strong>2)</strong> Next, we tell <code>createSourceViewer</code> to return
+ a <code>ProjectionViewer</code> instead of a <code>SourceViewer</code>. </p>
+<pre><font color="#0000FF">protected</font> ISourceViewer createSourceViewer(Composite parent,
+ IVerticalRuler ruler, <font color="#0000FF">int</font> styles)
+{
+ ISourceViewer viewer = <font color="#0000FF">new</font> ProjectionViewer(parent, ruler,
+ getOverviewRuler(), isOverviewRulerVisible(), styles);
+
+ <font color="#009933">// ensure decoration support has been created and configured.</font>
+ getSourceViewerDecorationSupport(viewer);
+
+ <font color="#0000FF">return</font> viewer;
+}
+</pre>
+
+<p><strong>3)</strong> Finally, we need some mechanism to tell the editor which
+ regions are collapsible. For that I have written a (very) small parser for XML
+ (which is very buggy and doesn't support nested elements). The parser runs as
+ a reconciling strategy and parses the entire document every time it is modified.
+ The parser then passes the range of every XML element to the editor, which then
+ in turn adds Projection Annotations to define collapsible regions.</p>
+ <p>
+ The source code for my simple parser is too large to show here, however, those
+ interested can take a look at the <code>XmlReconcilingStrategy.java</code>
+ file in the provided source code. </p>
+<p>Below is the code that does all this:</p>
+<pre><font color="#0000FF">private</font> Annotation[] oldAnnotations;
+<font color="#0000FF">public void</font> updateFoldingStructure(ArrayList positions)
+{
+ Annotation[] annotations = new Annotation[positions.size()];
+
+ <font color="#009933">//this will hold the new annotations along
+ //with their corresponding positions</font>
+ HashMap newAnnotations = new HashMap();
+
+ <font color="#0000FF">for</font>(<font color="#0000FF">int</font> i = 0; i < positions.size();i++)
+ {
+ ProjectionAnnotation annotation = <font color="#0000FF">new</font> ProjectionAnnotation();
+
+ newAnnotations.put(annotation, positions.get(i));
+
+ annotations[i] = annotation;
+ }
+
+ annotationModel.modifyAnnotations(oldAnnotations, newAnnotations,null);
+
+ oldAnnotations = annotations;
+}
+</pre>
+<p>Here is our completed editor with folding:</p>
+<p><img src="images/xmlEditor.png" width="331" height="203"></p>
+<h1>Source Code</h1>
+<p>All the source code that accompanies this article
+ may be found in the <a href="xmlEditorPlugin.zip">xmlEditorPlugin.zip file</a>.</p>
+<p><b>Update (19April2005):</b> My (buggy) xml parser has been replaced by a better one from
+Gerd Castan which supports nested xml elements.
+</p>
+<h1>Conclusion</h1>
+<p>By now, you should have understood the UI independent and dependent infrastructure
+ used in JFace Text to implement the folding capability. You should also have
+ understood how to implement folding in the text editor of your eclipse plug-in.
+ Plus you even got a free XML editor for Eclipse with folding support ;-).</p>
+<h1>References</h1>
+<ul>
+ <li><a href="http://devresource.hp.com/drc/technical_white_papers/eclipeditor/index.jsp" target="_blank">Creating a text-based editor for Eclipse</a></li>
+ <li>Articles in the Eclipse 3.0 Faqs book on text editors:
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq262.html" target="_blank">[FAQ262]</a>
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq263.html" target="_blank">[FAQ263]</a>
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq264.html" target="_blank">[FAQ264]</a>
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq265.html" target="_blank">[FAQ265]</a>
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq266.html" target="_blank">[FAQ266]</a>
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq267.html" target="_blank">[FAQ267]</a>
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq268.html" target="_blank">[FAQ268]</a>
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq269.html" target="_blank">[FAQ269]</a>
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq270.html" target="_blank">[FAQ270]</a>
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq271.html" target="_blank">[FAQ271]</a>
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq272.html" target="_blank">[FAQ272]</a>
+ <a href="http://www.eclipsefaq.org/chris/faq/html/faq273.html" target="_blank">[FAQ273]</a>
+ </li>
+ <li><a href="http://help.eclipse.org/help30/topic/org.eclipse.platform.doc.isv/guide/editors.htm" target="_blank">Online help for Editors</a></li>
+ <li><a href="http://help.eclipse.org/help30/topic/org.eclipse.platform.doc.isv/samples/org.eclipse.ui.examples.javaeditor/doc-html/ui_javaeditor_ex.html" target="_blank">Online help for the Java editor example</a></li>
+</ul>
+<small>Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.</small>
+</body>
+</html>
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/Idea.jpg b/Article-Folding-in-Eclipse-Text-Editors/images/Idea.jpg
new file mode 100644
index 0000000..119ce70
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/Idea.jpg
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/Thumbs.db b/Article-Folding-in-Eclipse-Text-Editors/images/Thumbs.db
new file mode 100644
index 0000000..a4624d8
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/Thumbs.db
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/annotationSummary.png b/Article-Folding-in-Eclipse-Text-Editors/images/annotationSummary.png
new file mode 100644
index 0000000..1f05d49
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/annotationSummary.png
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/hover.png b/Article-Folding-in-Eclipse-Text-Editors/images/hover.png
new file mode 100644
index 0000000..450a1dd
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/hover.png
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/linux_only.gif b/Article-Folding-in-Eclipse-Text-Editors/images/linux_only.gif
new file mode 100644
index 0000000..7c135cf
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/linux_only.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/note.gif b/Article-Folding-in-Eclipse-Text-Editors/images/note.gif
new file mode 100644
index 0000000..f6260db
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/note.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/projectionAnnotation.png b/Article-Folding-in-Eclipse-Text-Editors/images/projectionAnnotation.png
new file mode 100644
index 0000000..20b2253
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/projectionAnnotation.png
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/tag_1.gif b/Article-Folding-in-Eclipse-Text-Editors/images/tag_1.gif
new file mode 100644
index 0000000..4859d6f
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/tag_1.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/tag_2.gif b/Article-Folding-in-Eclipse-Text-Editors/images/tag_2.gif
new file mode 100644
index 0000000..5ea43dc
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/tag_2.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/tag_3.gif b/Article-Folding-in-Eclipse-Text-Editors/images/tag_3.gif
new file mode 100644
index 0000000..a69b68e
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/tag_3.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/tag_4.gif b/Article-Folding-in-Eclipse-Text-Editors/images/tag_4.gif
new file mode 100644
index 0000000..a1ad63f
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/tag_4.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/tag_5.gif b/Article-Folding-in-Eclipse-Text-Editors/images/tag_5.gif
new file mode 100644
index 0000000..d86a748
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/tag_5.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/tag_6.gif b/Article-Folding-in-Eclipse-Text-Editors/images/tag_6.gif
new file mode 100644
index 0000000..b9eb4ec
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/tag_6.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/tag_7.gif b/Article-Folding-in-Eclipse-Text-Editors/images/tag_7.gif
new file mode 100644
index 0000000..5f0e8fa
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/tag_7.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/tip.gif b/Article-Folding-in-Eclipse-Text-Editors/images/tip.gif
new file mode 100644
index 0000000..77b2451
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/tip.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/tryit.gif b/Article-Folding-in-Eclipse-Text-Editors/images/tryit.gif
new file mode 100644
index 0000000..f4927a4
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/tryit.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/win_only.gif b/Article-Folding-in-Eclipse-Text-Editors/images/win_only.gif
new file mode 100644
index 0000000..895f9ca
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/win_only.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/withFolding.png b/Article-Folding-in-Eclipse-Text-Editors/images/withFolding.png
new file mode 100644
index 0000000..b3a624b
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/withFolding.png
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/withoutFolding.png b/Article-Folding-in-Eclipse-Text-Editors/images/withoutFolding.png
new file mode 100644
index 0000000..48173ca
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/withoutFolding.png
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/xmlEditor.png b/Article-Folding-in-Eclipse-Text-Editors/images/xmlEditor.png
new file mode 100644
index 0000000..d10a481
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/xmlEditor.png
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/images/xmlEditor1.gif b/Article-Folding-in-Eclipse-Text-Editors/images/xmlEditor1.gif
new file mode 100644
index 0000000..8bc86c2
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/images/xmlEditor1.gif
Binary files differ
diff --git a/Article-Folding-in-Eclipse-Text-Editors/xmlEditorPlugin.zip b/Article-Folding-in-Eclipse-Text-Editors/xmlEditorPlugin.zip
new file mode 100644
index 0000000..3f528f8
--- /dev/null
+++ b/Article-Folding-in-Eclipse-Text-Editors/xmlEditorPlugin.zip
Binary files differ
diff --git a/Article-GEF-Draw2d/GEF-Draw2d.html b/Article-GEF-Draw2d/GEF-Draw2d.html
new file mode 100644
index 0000000..a600125
--- /dev/null
+++ b/Article-GEF-Draw2d/GEF-Draw2d.html
@@ -0,0 +1,379 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<TITLE>Displaying a UML Diagram with Draw2D</TITLE>
+<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
+<META content="Microsoft FrontPage 5.0" name=GENERATOR>
+<LINK href="../default_style.css" rel=stylesheet>
+</HEAD>
+<BODY vLink=#800080 link=#0000FF>
+<DIV align=right>&nbsp; <FONT face="Times New Roman, Times, serif"><FONT
+ size=-1>Copyright © 2003 International Business Machines Corp.</FONT></FONT></DIV>
+&nbsp;
+<DIV align=right>
+<TABLE cellSpacing=0 cellPadding=2 width="100%" border=0>
+ <TBODY>
+ <TR>
+ <TD vAlign=top align=left bgColor=#0080c0 colSpan=2><B><FONT
+ face=Arial,Helvetica><FONT color=#ffffff>&nbsp;Eclipse Corner
+ Article</FONT></FONT></B></TD>
+ </TR>
+ </TBODY>
+</TABLE>
+</DIV>
+<H1><IMG border="0" src="images/Idea.jpg" width="120" height="86"></H1>
+<CENTER>
+<H1>Display a UML Diagram using Draw2D</H1>
+</CENTER>
+<BLOCKQUOTE><B>Summary</B><BR>
+ The Graphical Editing Framework (GEF) ships with a painting and layout plug-in
+ called <b>Draw2D</b>. Draw2D provides figures and layout managers which form
+ the graphical layer of a GEF application. This article focuses only on the use
+ of Draw2D to render a simple UML class diagram.&nbsp; While Draw2D can be used
+ for standalone purposes, it is not an editing framework.&nbsp; Most applications
+ will use the GEF plug-in as the editing layer.
+ <P><B>By Daniel Lee, IBM</B><BR>
+ <FONT size=-1>August 25, 2003</FONT></P>
+</BLOCKQUOTE>
+<HR width="100%">
+
+<H1>Introduction</H1>
+<P>Draw2d provides lightweight rendering and layout capabilities on an SWT Canvas.
+ Figures, Layout Managers, and Borders can be combined and nested to create more
+ complex figures to suit just about any application. Choosing the right combination
+ of figures and layouts to create the desired effect can be a delicate task.
+ This article will walk you through creating a complex figure. </P>
+<P>Due to the scope of this article, the example code presented uses
+Draw2d in isolation, but most applications will use GEF and Draw2d together.<BR>
+</P>
+
+<H1>Creating the Draw2d Figure</H1>
+<H2>An Example</H2>
+This article will be based upon the creation of the following Draw2d
+Figure, a simplified UML class diagram:
+<BR>
+<BR>
+<DIV align="center"><IMG border="0" src="images/classDiagGIF.gif" width="154"
+ height="91"></DIV>
+<H2>Designing the Figure</H2>
+The first step in the creation of a figure is to decide on the
+components that will comprise the figure, and how they will be
+arranged.
+<P>The example figure is composed of three children figures. The composition itself
+ is named <b>UMLClassFigure</b>. Its first child, a <code>Label</code> figure,
+ will display the class name (&quot;Table&quot; in this example).&nbsp; The next
+ two children are containers for the class' attributes and methods.&nbsp; We
+ will create a figure called <b>CompartmentFigure</b> for this purpose. Both
+ the class and compartment figures will use a <code>ToolbarLayout</code> to place
+ their children. Here is a conceptual diagram of the overall structure:</P>
+<P align="center"><IMG border="0" src="images/UMLDiagGIF.gif" width="536"
+ height="404"></P>
+<H2>Creating the CompartmentFigure Class</H2>
+<P>CompartmentFigure is used to hold both methods and attributes. This class extends
+ org.eclipse.draw2d.Figure, and uses a ToolbarLayout to place its children. In
+ addition, CompartmentFigure uses a custom border. This border simply paints
+ a line 1 pixel in thickness across its top, to serve as the separator between
+ the CompartmentFigures. The code for CompartmentFigure is as follows:</P>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+<td><pre>public class CompartmentFigure extends Figure {
+
+ public CompartmentFigure() {
+ ToolbarLayout layout = new ToolbarLayout();
+ layout.setMinorAlignment(ToolbarLayout.ALIGN_TOPLEFT);
+ layout.setStretchMinorAxis(false);
+ layout.setSpacing(2);
+ setLayoutManager(layout);
+ setBorder(new CompartmentFigureBorder());
+ }
+
+ public class CompartmentFigureBorder extends AbstractBorder {
+ public Insets getInsets(IFigure figure) {
+ return new Insets(1,0,0,0);
+ }
+ public void paint(IFigure figure, Graphics graphics, Insets insets) {
+ graphics.drawLine(getPaintRectangle(figure, insets).getTopLeft(),
+ tempRect.getTopRight());
+ }
+ }
+}</pre></td>
+ </tr>
+</table>
+<H2>Creating the UMLClassFigure Class</H2>
+<P>The UMLClassFigure class is in many ways similar to the
+CompartmentFigure class. It contains three children -- two
+CompartmentFigures for attributes and methods and a Draw2d Label to
+display the class name. It also uses a vertically oriented ToolbarLayout to
+place its children. UMLClassFigure uses Draw2d's
+LineBorder to draw a box around its edges. The
+code for the UMLClassFigure class is as follows:</P>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>public class UMLClassFigure extends Figure {
+ public static Color classColor = new Color(null,255,255,206);
+ private CompartmentFigure attributeFigure = new CompartmentFigure();
+ private CompartmentFigure methodFigure = new CompartmentFigure();
+ public UMLClassFigure(Label name) {
+ ToolbarLayout layout = new ToolbarLayout();
+ setLayoutManager(layout);
+ setBorder(new LineBorder(ColorConstants.black,1));
+ setBackgroundColor(classColor);
+ setOpaque(true);
+
+ add(name);
+ add(attributeFigure);
+ add(methodFigure);
+ }
+ public CompartmentFigure getAttributesCompartment() {
+ return attributeFigure;
+ }
+ public CompartmentFigure getMethodsCompartment() {
+ return methodFigure;
+ }
+}</pre></td>
+ </tr>
+</table>
+<H2>Adding a Connection</H2>
+<P>Draw2d offers a special type of figure, called a connection, for connecting two figures.
+ To create a
+connection in Draw2d, it is first necessary to establish the two
+endpoints of the connection. These endpoints are called the
+<I>source</I> and the <I>target</I> anchors. Endpoints are created
+using objects that implement the ConnectionAnchor interface. Once these
+anchors are created, they are set as endpoints via calls to the
+connection's setSourceAnchor(ConnectionAnchor) and
+setTargetAnchor(ConnectionAnchor) methods. This is demonstrated below
+using a ChopboxAnchor. This type of anchor places the connection
+endpoint on the edge of the figure and causes it to point towards the figure's
+center.</P>
+
+
+<P>The following code demonstrates the addition of a connection:</P>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>PolylineConnection c = new PolylineConnection();
+ChopboxAnchor sourceAnchor = new ChopboxAnchor(classFigure);
+ChopboxAnchor targetAnchor = new ChopboxAnchor(classFigure2);
+c.setSourceAnchor(sourceAnchor);
+c.setTargetAnchor(targetAnchor);</pre></td>
+</tr>
+</table>
+<P align="center"><IMG border="0" src="images/classDiagConnectionGIF.gif"
+ width="355" height="343"> <B><BR>
+Two UMLClassFigures connected by a PolyLineConnection </B></P>
+<P align="center"><B></B><BR>
+</P>
+<H2>Adding a Decoration to the Connection</H2>
+<P>Draw2d also provides means for endpoint decorations, such as
+arrow-tips. Staying with the UML theme, we will create a decoration that
+represents a composed relationship, which is shown in UML as a filled
+diamond. This is done using a PolygonDecoration. The default shape of a
+PolygonDecoration is a filled arrowhead, but any shape can be used by creating a template for the decoration using a
+PointList, and calling the PolygonDecoration's setTemplate(PointList)
+method.<BR>
+<P>The following code demonstrates the addition of a PolygonDecoration
+to a Connection:</P>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>PolygonDecoration decoration = new PolygonDecoration();
+PointList decorationPointList = new PointList();
+decorationPointList.addPoint(0,0);
+decorationPointList.addPoint(-2,2);
+decorationPointList.addPoint(-4,0);
+decorationPointList.addPoint(-2,-2);
+decoration.setTemplate(decorationPointList);
+c.setSourceDecoration(decoration);</pre></td>
+</tr>
+</table>
+<P align="center"><IMG border="0" src="images/classDiagDecoGIF.gif" width="350"
+ height="335"><B><BR>
+Connection with a PolygonDecoration </B><BR>
+<BR>
+</P>
+<H2>Adding Labels to the Connection Using Locators</H2>
+<P>In addition to decorations, it is possible to add other Draw2d
+figures to the connection itself. This is done by calling the
+connection's add(IFigure figure, Object constraint) method where
+'figure' is the figure that you wish to add, and 'constraint' is an
+object that implements the Locator interface. The Locator places the figure on the connection. We will
+use this technique to add labels to our class diagram.
+The ConnectionEndpointLocator will be used for these labels. This
+locator places its figure relative to the connection's source or target endpoint. It allows the user to define the distance that the figure will appear relative to the end point via its
+setUDistance(int) and setVDistance(int) methods. (uDistance is the distance from the connection's owner to the figure. vDistance is the distance from the figure to the connection itself).</P>
+<P>The following code demonstrates the use of ConnectionEndpointLocators
+to add Labels to a Connection:</P>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>ConnectionEndpointLocator targetEndpointLocator =
+ new ConnectionEndpointLocator(c, true);
+targetEndpointLocator.setVDistance(15);
+Label targetMultiplicityLabel = new Label(&quot;1..*&quot;);
+c.add(targetMultiplicityLabel, targetEndpointLocator);
+ConnectionEndpointLocator sourceEndpointLocator =
+ new ConnectionEndpointLocator(c, false);
+sourceEndpointLocator.setVDistance(15);
+Label sourceMultiplicityLabel = new Label(&quot;1&quot;);
+c.add(sourceMultiplicityLabel, sourceEndpointLocator);
+
+ConnectionEndpointLocator relationshipLocator =
+ new ConnectionEndpointLocator(c,true);
+relationshipLocator.setUDistance(30);
+relationshipLocator.setVDistance(-20);
+Label relationshipLabel = new Label(&quot;contains&quot;);
+c.add(relationshipLabel,relationshipLocator);
+</pre></td>
+</tr>
+</table>
+<P align="center"><IMG border="0" src="images/classDiagLabelsGIF.gif"
+ width="344" height="334"><BR>
+<B>Adding Labels to the Connection </B></P>
+<H1>Creating a Test Class</H1>
+<P>This class contains a main method that creates an SWT shell and
+places a Draw2d LightweightSystem on that shell. The LightweightSystem
+ class provides the link between SWT and Draw2d. The test
+class creates a Draw2d figure to act as the contents of the
+LightweightSystem and adds two UMLClassFigures to this figure. It then
+connects the two class figures with a polyline connection, adds a
+diamond polygon decorator, and adds the UML relationship labels to the
+connection.<BR>
+<BR>
+This class uses the following images: { <IMG border="0"
+ src="images/field_private_obj.gif" width="16" height="16"> <IMG border="0"
+ src="images/methpub_obj.gif" width="16" height="16"> <IMG border="0"
+ src="images/class_obj.gif" width="16" height="16"> }. Download them and place them at
+the root of a Java project directory.<BR>
+</P>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td>
+ <pre>import org.eclipse.draw2d.*;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * A test class to display a UMLFigure
+ */
+public class UMLClassFigureTest {
+ public static void main(String args[]){
+ Display d = new Display();
+ final Shell shell = new Shell(d);
+ shell.setSize(400, 400);
+ shell.setText(&quot;UMLClassFigure Test&quot;);
+ LightweightSystem lws = new LightweightSystem(shell);
+ Figure contents = new Figure();
+ XYLayout contentsLayout = new XYLayout();
+ contents.setLayoutManager(contentsLayout);
+
+ Font classFont = new Font(null, &quot;Arial&quot;, 12, SWT.BOLD);
+ Label classLabel1 = new Label(&quot;Table&quot;, new Image(d,
+ UMLClassFigureTest.class.getResourceAsStream(&quot;class_obj.gif&quot;)));
+ classLabel1.setFont(classFont);
+
+ Label classLabel2 = new Label(&quot;Column&quot;, new Image(d,
+ UMLClassFigureTest.class.getResourceAsStream(&quot;class_obj.gif&quot;)));
+ classLabel2.setFont(classFont);
+
+ final UMLClassFigure classFigure = new UMLClassFigure(classLabel1);
+ final UMLClassFigure classFigure2 = new UMLClassFigure(classLabel2);
+
+ Label attribute1 = new Label(&quot;columns: Column[]&quot;, new Image(d,
+ UMLClassFigure.class.getResourceAsStream(&quot;field_private_obj.gif&quot;)));
+ Label attribute2 = new Label(&quot;rows: Row[]&quot;, new Image(d,
+ UMLClassFigure.class.getResourceAsStream(&quot;field_private_obj.gif&quot;)));
+ Label attribute3 = new Label(&quot;columnID: int&quot;, new Image(d,
+ UMLClassFigure.class.getResourceAsStream(&quot;field_private_obj.gif&quot;)));
+ Label attribute4 = new Label(&quot;items: List&quot;, new Image(d,
+ UMLClassFigure.class.getResourceAsStream(&quot;field_private_obj.gif&quot;)));
+
+ classFigure.getAttributesCompartment().add(attribute1);
+ classFigure.getAttributesCompartment().add(attribute2);
+ classFigure2.getAttributesCompartment().add(attribute3);
+ classFigure2.getAttributesCompartment().add(attribute4);
+
+ Label method1 = new Label(&quot;getColumns(): Column[]&quot;, new Image(d,
+ UMLClassFigure.class.getResourceAsStream(&quot;methpub_obj.gif&quot;)));
+ Label method2 = new Label(&quot;getRows(): Row[]&quot;, new Image(d,
+ UMLClassFigure.class.getResourceAsStream(&quot;methpub_obj.gif&quot;)));
+ Label method3 = new Label(&quot;getColumnID(): int&quot;, new Image(d,
+ UMLClassFigure.class.getResourceAsStream(&quot;methpub_obj.gif&quot;)));
+ Label method4 = new Label(&quot;getItems(): List&quot;, new Image(d,
+ UMLClassFigure.class.getResourceAsStream(&quot;methpub_obj.gif&quot;)));
+
+ classFigure.getMethodsCompartment().add(method1);
+ classFigure.getMethodsCompartment().add(method2);
+ classFigure2.getMethodsCompartment().add(method3);
+ classFigure2.getMethodsCompartment().add(method4);
+
+ contentsLayout.setConstraint(classFigure, new Rectangle(10,10,-1,-1));
+ contentsLayout.setConstraint(classFigure2, new Rectangle(200, 200, -1, -1));
+
+ /* Creating the connection */
+ PolylineConnection c = new PolylineConnection();
+ ChopboxAnchor sourceAnchor = new ChopboxAnchor(classFigure);
+ ChopboxAnchor targetAnchor = new ChopboxAnchor(classFigure2);
+ c.setSourceAnchor(sourceAnchor);
+ c.setTargetAnchor(targetAnchor);
+
+ /* Creating the decoration */
+ PolygonDecoration decoration = new PolygonDecoration();
+ PointList decorationPointList = new PointList();
+ decorationPointList.addPoint(0,0);
+ decorationPointList.addPoint(-2,2);
+ decorationPointList.addPoint(-4,0);
+ decorationPointList.addPoint(-2,-2);
+ decoration.setTemplate(decorationPointList);
+ c.setSourceDecoration(decoration);
+
+ /* Adding labels to the connection */
+ ConnectionEndpointLocator targetEndpointLocator =
+ new ConnectionEndpointLocator(c, true);
+ targetEndpointLocator.setVDistance(15);
+ Label targetMultiplicityLabel = new Label(&quot;1..*&quot;);
+ c.add(targetMultiplicityLabel, targetEndpointLocator);
+
+ ConnectionEndpointLocator sourceEndpointLocator =
+ new ConnectionEndpointLocator(c, false);
+ sourceEndpointLocator.setVDistance(15);
+ Label sourceMultiplicityLabel = new Label(&quot;1&quot;);
+ c.add(sourceMultiplicityLabel, sourceEndpointLocator);
+
+ ConnectionEndpointLocator relationshipLocator =
+ new ConnectionEndpointLocator(c,true);
+ relationshipLocator.setUDistance(10);
+ relationshipLocator.setVDistance(-20);
+ Label relationshipLabel = new Label(&quot;contains&quot;);
+ c.add(relationshipLabel,relationshipLocator);
+
+ contents.add(classFigure);
+ contents.add(classFigure2);
+ contents.add(c);
+
+ lws.setContents(contents);
+ shell.open();
+ while (!shell.isDisposed())
+ while (!d.readAndDispatch())
+ d.sleep();
+ }
+}</pre></td>
+ </tr>
+</table>
+<H1>Conclusions</H1>
+<P>This article has served as an introduction to the customized use of
+the Graphical Editing Framework's visual component, Draw2d figures. The
+concepts of Draw2d connections, decorations, and locators have also been
+introduced. For more information on GEF, see the GEF website. (<A
+ href="http://www.eclipse.org/gef">http://www.eclipse.org/gef</A>).</P>
+<H2><BR>
+Acknowledgements</H2>
+<P>The author would like to thank Randy Hudson and Eric Bordeau for
+providing constructive comments on the article.</P>
+<P><SMALL>Java and all Java-based trademarks and logos are trademarks or
+registered trademarks of Sun Microsystems, Inc. in the United States,
+other countries, or both.</SMALL></P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/Article-GEF-Draw2d/images/Idea.jpg b/Article-GEF-Draw2d/images/Idea.jpg
new file mode 100644
index 0000000..119ce70
--- /dev/null
+++ b/Article-GEF-Draw2d/images/Idea.jpg
Binary files differ
diff --git a/Article-GEF-Draw2d/images/UMLDiagGIF.gif b/Article-GEF-Draw2d/images/UMLDiagGIF.gif
new file mode 100644
index 0000000..3c8e9f5
--- /dev/null
+++ b/Article-GEF-Draw2d/images/UMLDiagGIF.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/classDiagConnectionGIF.gif b/Article-GEF-Draw2d/images/classDiagConnectionGIF.gif
new file mode 100644
index 0000000..3e9f5b0
--- /dev/null
+++ b/Article-GEF-Draw2d/images/classDiagConnectionGIF.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/classDiagDecoGIF.gif b/Article-GEF-Draw2d/images/classDiagDecoGIF.gif
new file mode 100644
index 0000000..1dbcae1
--- /dev/null
+++ b/Article-GEF-Draw2d/images/classDiagDecoGIF.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/classDiagGIF.gif b/Article-GEF-Draw2d/images/classDiagGIF.gif
new file mode 100644
index 0000000..b7a9f55
--- /dev/null
+++ b/Article-GEF-Draw2d/images/classDiagGIF.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/classDiagLabelsGIF.gif b/Article-GEF-Draw2d/images/classDiagLabelsGIF.gif
new file mode 100644
index 0000000..bfb9598
--- /dev/null
+++ b/Article-GEF-Draw2d/images/classDiagLabelsGIF.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/class_obj.gif b/Article-GEF-Draw2d/images/class_obj.gif
new file mode 100644
index 0000000..cf33d93
--- /dev/null
+++ b/Article-GEF-Draw2d/images/class_obj.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/field_private_obj.gif b/Article-GEF-Draw2d/images/field_private_obj.gif
new file mode 100644
index 0000000..864feee
--- /dev/null
+++ b/Article-GEF-Draw2d/images/field_private_obj.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/linux_only.gif b/Article-GEF-Draw2d/images/linux_only.gif
new file mode 100644
index 0000000..7c135cf
--- /dev/null
+++ b/Article-GEF-Draw2d/images/linux_only.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/methpub_obj.gif b/Article-GEF-Draw2d/images/methpub_obj.gif
new file mode 100644
index 0000000..ecf40d2
--- /dev/null
+++ b/Article-GEF-Draw2d/images/methpub_obj.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/tag_1.gif b/Article-GEF-Draw2d/images/tag_1.gif
new file mode 100644
index 0000000..4859d6f
--- /dev/null
+++ b/Article-GEF-Draw2d/images/tag_1.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/tag_2.gif b/Article-GEF-Draw2d/images/tag_2.gif
new file mode 100644
index 0000000..5ea43dc
--- /dev/null
+++ b/Article-GEF-Draw2d/images/tag_2.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/tag_3.gif b/Article-GEF-Draw2d/images/tag_3.gif
new file mode 100644
index 0000000..a69b68e
--- /dev/null
+++ b/Article-GEF-Draw2d/images/tag_3.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/tag_4.gif b/Article-GEF-Draw2d/images/tag_4.gif
new file mode 100644
index 0000000..a1ad63f
--- /dev/null
+++ b/Article-GEF-Draw2d/images/tag_4.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/tag_5.gif b/Article-GEF-Draw2d/images/tag_5.gif
new file mode 100644
index 0000000..d86a748
--- /dev/null
+++ b/Article-GEF-Draw2d/images/tag_5.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/tag_6.gif b/Article-GEF-Draw2d/images/tag_6.gif
new file mode 100644
index 0000000..b9eb4ec
--- /dev/null
+++ b/Article-GEF-Draw2d/images/tag_6.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/tag_7.gif b/Article-GEF-Draw2d/images/tag_7.gif
new file mode 100644
index 0000000..5f0e8fa
--- /dev/null
+++ b/Article-GEF-Draw2d/images/tag_7.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/tip.gif b/Article-GEF-Draw2d/images/tip.gif
new file mode 100644
index 0000000..77b2451
--- /dev/null
+++ b/Article-GEF-Draw2d/images/tip.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/tryit.gif b/Article-GEF-Draw2d/images/tryit.gif
new file mode 100644
index 0000000..f4927a4
--- /dev/null
+++ b/Article-GEF-Draw2d/images/tryit.gif
Binary files differ
diff --git a/Article-GEF-Draw2d/images/win_only.gif b/Article-GEF-Draw2d/images/win_only.gif
new file mode 100644
index 0000000..895f9ca
--- /dev/null
+++ b/Article-GEF-Draw2d/images/win_only.gif
Binary files differ
diff --git a/Article-GEF-EMF/article_style.css b/Article-GEF-EMF/article_style.css
new file mode 100644
index 0000000..971fa21
--- /dev/null
+++ b/Article-GEF-EMF/article_style.css
@@ -0,0 +1,25 @@
+table.content {
+ background-color: white;
+ text-align: left;
+ margin-left:auto;
+ margin-right:auto;
+ cellpadding: 20;
+}
+div.figure {
+ background-color: white;
+ text-align: center;
+}
+div.fileContent {
+ background-color: white;
+ text-align: left;}
+div.figure-caption {
+ text-align: center;
+ border-top-width: thin;
+ border-right-width: thin;
+ border-bottom-width: thin;
+ border-left-width: thin;
+ border-top-style: solid;
+ border-top-color: #FFFFFF;}
+span.figure-number { font-weight: bold;}
+pre.program { margin-left: 1em; margin-right: 1em; padding: 5px; background-color: whitesmoke;}
+
diff --git a/Article-GEF-EMF/files/shapesemf.zip b/Article-GEF-EMF/files/shapesemf.zip
new file mode 100644
index 0000000..c81fa94
--- /dev/null
+++ b/Article-GEF-EMF/files/shapesemf.zip
Binary files differ
diff --git a/Article-GEF-EMF/files/shapesmerlin.zip b/Article-GEF-EMF/files/shapesmerlin.zip
new file mode 100644
index 0000000..5841eea
--- /dev/null
+++ b/Article-GEF-EMF/files/shapesmerlin.zip
Binary files differ
diff --git a/Article-GEF-EMF/files/shapesrcp.zip b/Article-GEF-EMF/files/shapesrcp.zip
new file mode 100644
index 0000000..2faf727
--- /dev/null
+++ b/Article-GEF-EMF/files/shapesrcp.zip
Binary files differ
diff --git a/Article-GEF-EMF/gef-emf.html b/Article-GEF-EMF/gef-emf.html
new file mode 100644
index 0000000..30aa6f8
--- /dev/null
+++ b/Article-GEF-EMF/gef-emf.html
@@ -0,0 +1,758 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+ <head>
+ <meta name="generator" content="HTML Tidy, see www.w3.org">
+ <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+ <meta name="author" content="Chris Aniszczyk">
+
+ <title>Using GEF with EMF</title>
+ <link type="text/css" rel="stylesheet" href="../default_style.css">
+ <link type="text/css" rel="stylesheet" href="article_style.css">
+ </head>
+
+ <body>
+ <div align="right">
+ &nbsp; <span class="copy">Copyright &copy; 2005 IBM Corporation</span>
+
+ <table border="0" cellpadding="2" cellspacing="0" width="100%">
+ <tbody>
+ <tr>
+ <td colspan="2" align="left" bgcolor="#0080C0" valign="top"><span
+ class="corner">&nbsp;Eclipse Corner Article</span> </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ <div align="left">
+ <h1><img src="../images/Idea.jpg" height="86" width="120" align=
+ "middle"></h1>
+ </div>
+
+ <p>&nbsp;</p>
+
+ <h1 align="center">Using GEF with EMF</h1>
+
+ <blockquote>
+ <p><b>Summary</b></p>
+
+ <p>The Graphical Editing Framework (GEF) provides a framework for
+ creating visual editors while being model agnostic. In most cases, people
+ bring their own model which tend to be based on Plain Old Java Objects
+ (POJOs). An alternative using POJOs is the Eclipse Modeling Framework
+ (EMF), which provides many features for manipulating models that aren't
+ found in POJOs. The purpose of this article is to build upon the shapes
+ example provided by GEF using the Eclipse Modeling Framework (EMF) and to
+ provide an introduction using EMF based models in GEF based editors.</p>
+
+ <p><b>Chris Aniszczyk, IBM</b><br>
+ <font size="-1">June 8, 2005</font></p>
+ </blockquote>
+ <hr>
+
+ <h3>Environment</h3>
+
+ <p>The examples in this article were built and tested on:</p>
+
+ <ul>
+ <li><a href=
+ "http://download.eclipse.org/eclipse/downloads/drops/S-3.1RC1-200505271300/index.php">
+ Eclipse 3.1RC1</a></li>
+
+ <li><a href=
+ "http://download.eclipse.org/tools/gef/downloads/drops/S-3.1M7-200505231916/index.php">
+ GEF 3.1M7</a></li>
+
+ <li><a href=
+ "http://download.eclipse.org/tools/emf/scripts/downloads-viewer.php?s=2.1.0/I200505261142">
+ EMF 2.1.0</a></li>
+ </ul>
+
+ <p>There is no guarantee the examples will work with other versions.</p>
+
+
+ <h2>Introduction</h2>
+
+ <p>The <a href="http://www.eclipse.org/gef">Graphical Editing Framework
+ (GEF)</a> assumes that you have a model of some type. The <i>type</i> in
+ most cases, is a set of custom Java classes created to suit the needs of an
+ application. Overlaying the model, users would implement their own observer
+ pattern. For example, when an object changes state, GEF becomes aware of
+ the change, and performs the appropriate action, such as redrawing a figure
+ due to a move request. Users spend time building their own viewers (i.e.
+ properties) and deciding how the model should be persisted. Most novices
+ learning GEF don't realize EMF can help with several modeling issues
+ previously mentioned. The <a href="http://www.eclipse.org/emf">Eclipse
+ Modeling Framework (EMF)</a> is a Java framework and code generation
+ facility for building tools and other applications based on a structured
+ model. EMF consists of two fundamental frameworks: the core framework,
+ responsible for basic code generation, and runtime, responsible for
+ creation of Java implementation classes for a model. The EMF.edit framework
+ builds on the core framework to add support for generating adapter classes
+ that enable viewing and command-based editing of a model. Furthermore, EMF
+ provides a free adapter that listens for model changes, a requirement when
+ building a GEF editor. In addition, EMF includes default support for
+ persistence using XMI or XML (you can write your custom persistence layer
+ by extending a few classes) <a href="#EMFOverview">[1]</a>.</p>
+
+ <p>The purpose of the article is to build upon the shapes example that was
+ extensively evaluated in a previous Eclipse Corner article <a href=
+ "#">[2]</a>. The shapes model currently exists as a custom set of Java
+ objects, this article illustrates how to transform the shapes model into an
+ EMF-based model. The transformation occurs in two major steps: mapping
+ custom Java objects to an EMF model, and modify EditParts to use the new
+ features available in EMF.</p>
+
+ <h2>Shapes Transformation</h2>
+
+ <p>The transformation of the Shapes example will occur in the following
+ order:</p>
+
+ <ul>
+ <li>Map POJOs to an EMF model</li>
+
+ <li>Use PropertySources with your EMF model</li>
+
+ <li>Change EditPart to reflect new behavior of EMF models</li>
+ </ul>
+
+ <h3>Current Model</h3>
+
+ <p>The current shapes model (<b>see Figure 1</b>) was designed for
+ simplicity and for instructional purposes. It consists of the following
+ classes:</p>
+
+ <ul>
+ <li>
+ <i>ModelElement</i>
+
+ <ul>
+ <li>The base class of all shapes model objects. It serves two main
+ purposes: notification and property source support for the Eclipse
+ property viewer. This class will no longer be needed when
+ transitioning to EMF because EMF provides the necessary facilities to
+ listen for model changes and EMF.Edit provides property support.</li>
+ </ul>
+ </li>
+
+ <li>
+ <i>ShapesDiagram</i>
+
+ <ul>
+ <li>A container object to hold a collection of shapes.</li>
+ </ul>
+ </li>
+
+ <li>
+ <i>Connection</i>
+
+ <ul>
+ <li>A connection between two shapes codified into a source and target
+ connection.</li>
+ </ul>
+ </li>
+
+ <li>
+ <i>Shape</i>
+
+ <ul>
+ <li>An abstract class that represents a shape. It includes various
+ information regarding visual representation, including the source and
+ target connections of the object.</li>
+ </ul>
+ </li>
+
+ <li>
+ <i>RectangularShape / EllipticalShape</i>
+
+ <ul>
+ <li>Special classes that represent two types of <i>Shape</i>s:
+ rectangular and elliptical.</li>
+ </ul>
+ </li>
+ </ul>
+
+ <div class="figure">
+ <img src="images/shapesmodel.png"><br>
+
+
+ <div class="figure-caption">
+ <span class="figure-number">Figure 1</span>: Summarized Shapes Model
+ (without ModelElement)
+ </div>
+ </div>
+
+ <h3>Transformed Model</h3>
+
+ <p>To transform the simple shapes model, we must map it an EMF model. This
+ can be accomplished in many ways (i.e. XSD, Java, UML) and is discussed
+ further at the EMF documentation site <a href="#EMFDocumentation">[3]</a>.
+ For simplicity, this article will only focus on using annotated Java as EMF
+ input. Listed below are sketches representing the old shapes model and
+ their corresponding annotated Java models. After we have these models, we
+ can use EMF to generate the rest of the code needed to interact with our
+ models.</p>
+
+ <p><img src="../images/tip.gif">A tutorial is available that describes how
+ to generate an EMF model from annotated Java <a href=
+ "#EMFTutorial">[4]</a>.</p>
+
+ <table class="content" cellspacing="20">
+ <tbody>
+ <tr>
+ <td><img src="images/shapesdiagram.png"> </td>
+
+ <td>
+<pre class="program">
+/** @model */
+public interface ShapesDiagram {
+
+ /** @model type="Shape" containment="true" */
+ public List getShapes();
+
+}
+</pre>
+
+ <center>
+ <b>ShapesDiagram.java</b>
+ </center>
+ </td>
+ </tr>
+
+ <tr>
+ <td><img src="images/connection.png"> </td>
+
+ <td>
+<pre class="program">
+/** @model */
+public interface Connection {
+
+ /** @model */
+ public Shape getSource();
+
+ /** @model */
+ public Shape getTarget();
+
+ /** @model */
+ public boolean isDashed();
+
+ /** @model */
+ public void reconnect();
+
+ /** @model */
+ public void disconnect();
+
+}
+</pre>
+
+ <center>
+ <b>Connection.java</b>
+ </center>
+ </td>
+ </tr>
+
+ <tr>
+ <td><img src="images/shape.png"> </td>
+
+ <td>
+<pre class="program">
+/** @model abstract="true" */
+public interface Shape {
+
+ /** @model */
+ public int getX();
+
+ /** @model */
+ public int getY();
+
+ /** @model */
+ public int getWidth();
+
+ /** @model default="0" */
+ public int getHeight();
+
+ /** @model type="Connection" containment="true" */
+ List getSourceConnections();
+
+ /** @model type="Connection" */
+ List getTargetConnections();
+
+}
+</pre>
+
+ <center>
+ <b>Shape.java</b>
+ </center>
+ </td>
+ </tr>
+
+ <tr>
+ <td><img src="images/shapetypes.png"> </td>
+
+ <td>
+<pre class="program">
+/** @model */
+public interface RectangularShape extends Shape {
+
+}
+</pre>
+
+ <center>
+ <b>RectangularShape.java</b>
+ </center>
+<pre class="program">
+/** @model */
+public interface EllipticalShape extends Shape {
+
+}
+</pre>
+
+ <center>
+ <b>EllipticalShape.java</b>
+ </center>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h3>Properties for your EMF model</h3>
+
+ <p>Before I discuss how to add properties to your EMF model, I would like
+ to bring up the issue of notational model and semantic model separation. It
+ is considered good design to separate visual information from semantic
+ information. In the original shapes example, there was no logical
+ separation of the notational (visual) information, like size and location,
+ from the semantic information. For simplicity, this example will not
+ separate visual information from semantic information. Note the original
+ shapes example didn't have semantic information unless you can imagine the
+ shape model having a name attribute that would specify the name of a shape.
+ If you are curious to see this type of separation, the <a href=
+ "#Future">Looking to the Future</a> section discussed in this article
+ contains information of interest.</p>
+
+ <p>Eclipse provides a properties view that allows for the manipulation of
+ currently selected object properties as long as the object adheres to the
+ <i>IPropertySource</i> interface. In GEF, <i>AbstractEditPart</i> checks if
+ its model implements <i>IPropertySource</i>, if so the model is returned so
+ the Eclipse properties view can take advantage of it.</p>
+
+ <p>For simplicity reasons this example isn't taking advantage of EMF.edit
+ property source generation support. The reason being is that EMF and GEF
+ use different command stacks and command interfaces so they can't be used
+ together easily. In order to take advantage of EMF.edit, the user needs to
+ wrap EMF commands with GEF commands. If you think you are hot stuff, you
+ can further investigate this issue <a href="#CommandStackBug1">[5]</a> <a
+ href="#CommandStackBug2">[6]</a> in a few ways:</p>
+
+ <ul>
+ <li>Eclipse 3.1 features a common command infrastructure <a href=
+ "#CommonCommand">[7]</a> that projects may pick up.</li>
+
+ <li>The Graphical Modeling Framework (GMF) <a href="#GMFWebpage">[8]</a>
+ is an upcoming project and is discussed in <a href="#Future">Looking to
+ the Future</a> section.</li>
+
+ <li>The Merlin Generator Framework <a href="#MerlinWebpage">[9]</a>
+ discussed in <a href="#Future">Looking to the Future</a> contains
+ examples of using EMF.Edit with GEF based editors (there's also an
+ example in this article).</li>
+
+ <li>Examine GEF 3.1 EDiagram example <a href=
+ "#EDiagramCVSOldProperties">[10]</a> (older version used EMF.Edit to
+ display properties).</li>
+ </ul>
+
+ <p>In order to take advantage of Eclipse properties views we create classes
+ that implement the <i>IPropertySource</i> interface. To investigate how
+ this is accomplished, it is recommended to look at
+ <i>AbstractPropertySource</i> and its implementers. Listed below is an
+ example implementation, <i>ConnectionPropertySource</i> which needs to
+ define how a property is <img src="../images/tag_1.gif">retrieved and <img
+ src="../images/tag_2.gif">set.</p>
+<pre class="program">
+public class ConnectionPropertySource extends AbstractPropertySource {
+
+...
+
+ <img src="../images/tag_1.gif">public Object getPropertyValue(Object id) {
+ if(id == ID_STYLE) {
+ return Boolean.toString(getConnectionModel().isDashed());
+ }
+ return null;
+ }
+
+ <img src=
+"../images/tag_2.gif">public void setPropertyValue(Object id, Object value) {
+ if(id == ID_STYLE) {
+ getConnectionModel().setDashed(Boolean.valueOf((String) value));
+ }
+ }
+
+...
+
+}
+</pre>
+
+ <center>
+ <b>ConnectionPropertySource.java</b>
+ </center>
+
+ <h3>Listening to your EMF model</h3>
+
+ <p>In GEF, the EditParts act as controllers and receive notice of input and
+ then properly direct changes to its model and view objects. It also keeps
+ track of connections between the model objects and any other communication.
+ In the original shapes example <a href="#ShapeArticle">[2]</a>, every model
+ object extended the abstract class <i>ModelElement</i> which included
+ support for adding and removing listeners from model objects. This type of
+ behavior is possible with EMF since every EMF Object (<i>EObject</i>) is
+ also a <i>Notifier</i> which supports listening for objects.</p>
+
+ <p>We'll use the EditPart that represents a shape in the new example. In
+ <i>ShapeEditPart</i> we added a convenience method <i>hookIntoModel</i>
+ which provides the ability to pass a model object and <img src=
+ "../images/tag_1.gif">add a listener to the model. In order to add
+ listeners to EMF model objects, our listener (the EditPart) must implement
+ the <i>Adapter</i> interface. An important part of this interface is the
+ <i>notifyChanged</i> method which serves as the point where we will analyze
+ the types of changes that happen to our EMF model and act on them.
+ Furthermore, EMF provides the ability to filter based on the type of
+ notification your listener receives, whether it is a <img src=
+ "../images/tag_2.gif">set, <img src="../images/tag_4.gif">add, remove,
+ etc... (take a peek at the <i>Notification</i> class for what other filters
+ exist). The first case is when a visual value like <img src=
+ "../images/tag_3.gif">x-coordinate, y-coordinate, width or height is set.
+ Once we establish that a set happened on any of these visual elements, we
+ can properly call the <i>refreshVisuals</i> method to redraw the figure.
+ The next case is when a <img src="../images/tag_5.gif">source connection or
+ a target connection is <img src="../images/tag_4.gif">removed or added.
+ Since we know what type of connection is added or removed, we can tell the
+ EditPart which type of connections need to be refreshed.</p>
+
+ <table align="center" cellspacing="20">
+ <tbody>
+ <tr>
+ <td>
+<pre class="program">
+private void hookIntoModel(EObject model) {
+ if(model != null) {
+ <img src="../images/tag_1.gif">model.eAdapters().add(this);
+ }
+}
+</pre>
+
+ <center>
+ <b>ShapeEditPart.java</b>
+ </center>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+<pre class="program">
+public void notifyChanged(Notification notification) {
+ int type = notification.getEventType();
+ int featureId = notification.getFeatureID(ModelPackage.class);
+ switch(type) {
+ <img src="../images/tag_2.gif">case Notification.SET:
+ switch(featureId) {
+ <img src="../images/tag_3.gif">case ModelPackage.SHAPE__X:
+ <img src="../images/tag_3.gif">case ModelPackage.SHAPE__Y:
+ <img src="../images/tag_3.gif">case ModelPackage.SHAPE__WIDTH:
+ <img src="../images/tag_3.gif">case ModelPackage.SHAPE__HEIGHT:
+ refreshVisuals();
+ break;
+ }
+ <img src="../images/tag_4.gif">case Notification.ADD:
+ <img src="../images/tag_4.gif">case Notification.REMOVE:
+ switch(featureId) {
+ <img src=
+"../images/tag_5.gif">case ModelPackage.SHAPE__SOURCE_CONNECTIONS:
+ refreshSourceConnections();
+ break;
+ <img src=
+"../images/tag_5.gif">case ModelPackage.SHAPE__TARGET_CONNECTIONS:
+ refreshTargetConnections();
+ break;
+ }
+ }
+ }
+</pre>
+
+ <center>
+ <b>ShapeEditPart.java</b>
+ </center>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h2 id="Future">Looking to the Future</h2>
+
+ <p>There has been a considerable amount of work done trying to unite two of
+ the most popular Eclipse projects: EMF and GEF. In this section, I will
+ discuss some of that work and where it is headed. Also, this section serves
+ the ancillary purpose of pointing you to more complex examples if you gain
+ mastery of the example discussed in this article.</p>
+
+ <h3>GEF 3.1 EDiagram Example</h3>
+
+ <p>The GEF 3.1 release will include a new example (<b>see Figure 2</b>)
+ that lets you visualize and edit EMF models (Ecore). The source code is
+ available in CVS and is viewable online <a href="#EDiagramCVS">[11]</a>.
+ This example is fairly complex, but it illustrates how to separate
+ notational (diagram) logic from semantic (business) logic. It accomplishes
+ this by creating an EMF model EDiagram that represents the diagram logic.
+ Inside this model is the typical information associated with diagrams:
+ location, size, incoming connections, outgoing connections, etc.... The
+ semantic information is provided in the EMF model (.ecore file). I believe
+ the Shapes EMF example will serve as a good stepping stone in understanding
+ the complexities of the EDiagram example.</p>
+
+ <div class="figure">
+ <img src="images/ediagram.jpg">
+
+ <div class="figure-caption">
+ <span class="figure-number">Figure 2</span>: EDiagram Example (picture
+ shamelessly stolen from Ed Merks)
+ </div>
+ </div>
+
+ <h3>Graphical Modeling Framework (GMF)</h3>
+
+ <p>The GMF <a href="#GMFWebpage">[8]</a> is a new Eclipse project that is
+ currently in validation phase and entering the implementation phase soon.
+ The goal of GMF is to form a generative bridge between EMF and GEF, whereby
+ a diagram definition will be linked to a domain model as input to the
+ generation of a visual editor. The main components of GMF will be a
+ diagramming infrastructure that will provide a set of base diagramming
+ components that serve as a target for the next component, a diagram
+ generation framework. The Diagram Generation framework will use the diagram
+ definition input and generate code that is part of GMF's final component,
+ in addition it will provide exemplary modeling tools <a href=
+ "#GMFRequirements">[12]</a>. I encourage readers to browse the GMF <a href=
+ "news://news.eclipse.org/eclipse.technology.gmf">newsgroup</a> and webpage
+ <a href="#GMFWebpage">[8]</a> for more information. I believe the GMF
+ project will address a lot of the current concerns with building GEF
+ editors based on EMF models and make the process a lot easier.</p>
+
+
+ <h3>Merlin Generator Project</h3>
+
+ <p>Merlin is a free Eclipse plugin (EPL) <a href="#MerlinWebpage">[9]</a>,
+ based on EMF, that provides enhanced code generation and model
+ transformation tools. Also, Merlin comes with a set of wizards and editors
+ for customizing code generation and model transformations (including a JET
+ file editor with syntax coloring, code completion and validation). An
+ interesting subset of Merlin includes a built-in GEF generator (created
+ with Merlin's own mappings and templates) that allows users to generate GEF
+ editors from any EMF based model. Similar to the EDiagram example, this GEF
+ generator produces editors that store semantic and notational information
+ in different files. Additionally, the generator options can be amended so
+ custom figures are used for the EditParts. There are more features
+ contained with Merlin that won't be discussed since I deemed them outside
+ the scope of this article. Note that some of the features of Merlin may end
+ up in the GMF project as Merlin is a possible initial contributor.</p>
+
+ <p>To show the capabilities of Merlin and add some excitement to this
+ article, I used the shapes EMF model as input to Merlin and generated a
+ functional GEF editor (<b>see Figure 3</b>) that uses EMF for its model. It
+ took me all of a few seconds to create a fully functional EMF-based GEF
+ editor. I recommend users to look at Merlin once they are familiar with the
+ basics and look to tackle more complex problems. Note, there are two
+ examples with Merlin: There is a .gefgenmodel included with the shapes EMF
+ example and there is a separate contribution by the author of Merlin that
+ shows off a bit more advanced generation.</p>
+
+ <p><img src="../images/tip.gif">Used <a href=
+ "http://sourceforge.net/project/showfiles.php?group_id=125827&amp;package_id=137615&amp;release_id=330085">
+ Merlin 0.4.9</a> in this article<br>
+ </p>
+
+ <div class="figure">
+ <img src="images/shapesmerlin.png">
+
+ <div class="figure-caption">
+ <span class="figure-number">Figure 3</span>: Merlin based GEF editor using
+ a shapes model as input
+ </div>
+ </div>
+
+ <h2>Bonus: Shapes Example goes RCP!</h2>
+
+ <p>I spend a considerable amount of time browsing the Eclipse newsgroups
+ and one of the questions that comes up frequently in regards to GEF is
+ <i>how to use my GEF editor in an RCP based application</i>. I believe this
+ question is going to get asked more as the Eclipse 3.1 release sufficiently
+ increases the ease in building and deploying RCP-based applications. So,
+ for my last magic trick and to reward readers who got to this point, I'll
+ discuss how to convert the original shapes example into an RCP-based one
+ and provide the code!</p>
+
+ <p><img src="../images/tip.gif">If you are unfamiliar with RCP, the <a
+ href="http://www.eclipse.org/rcp/faq.html">RCP FAQ</a> is a good start.</p>
+
+ <p>The conversion of the shapes example into an RCP-based application is a
+ lot simpler than most people think. The problem stems from the
+ <i>setInput</i> method of <i>ShapesEditor</i> expecting an
+ <i>IEditorInput</i>, but the most familiar editor input people work with is
+ <i>IFileEditorInput</i>. The problem with <i>IFileEditorInput</i> is that
+ it belongs to the pesky <b>org.eclipse.ui.ide</b> plugin which is not an
+ acceptable dependency for an RCP-based application. The solution to this
+ problem is to simply create our own editor input, <i>ShapesEditorInput</i>
+ which implements the <i>IEditorInput</i> interface via
+ <i>IPathEditorInput</i> interface. Once this change is completed and the
+ <i>setInput</i> method is properly changed in <i>ShapesEditor</i> to use
+ <i>ShapesEditorInput</i>, we can now properly open a shapes editor. Note,
+ the sole purpose of this example is to demonstrate how to get a GEF editor
+ inside of an RCP application, it doesn't include support for various
+ actions such as saving or wizards (I leave this for the reader to
+ explore).</p>
+
+ <p><img src="../images/tip.gif">This concept of creating your own
+ <i>IEditorInput</i> can be applied to creating editors that aren't file
+ based (i.e. an editor which is based off of data from a database).</p>
+
+ <table align="center" cellspacing="20">
+ <tbody>
+ <tr>
+ <td>
+ <div class="figure">
+ <img src="images/shapesrcp.png">
+
+ <div class="figure-caption">
+ <span class="figure-number">Figure 4</span>: Shapes RCP Example
+ Product
+ </div>
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+<pre class="program">
+/**
+ * Uses a ShapesEditorInput to serve as a dummy editor input
+ * It is up to the editor input to supply the initial shapes diagram
+ *
+ * @see org.eclipse.ui.part.EditorPart#setInput(org.eclipse.ui.IEditorInput)
+ */
+protected void setInput(IEditorInput input) {
+ super.setInput(input);
+ ShapesEditorInput shapesInput = ((ShapesEditorInput) input);
+ diagram = shapesInput.getShapesDiagram();
+ setPartName(shapesInput.getName());
+}
+</pre>
+
+ <center>
+ <b>ShapesEditor.java</b>
+ </center>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <h2>Summary</h2>
+
+ <p>I made an attempt at giving you a simple example to learn how to
+ integrate EMF with GEF editors. I discussed step-by-step how to transform
+ the original shapes example into a EMF-based one. Also, I included
+ discussion of upcoming work that may yield more complex examples that you
+ may learn from using some of the knowledge gleaned from studying the shapes
+ EMF example. For my more attentive readers, I included an example that
+ ported the original shapes example to an RCP-based one. I understand that
+ there is a high learning curve associated with these two complex frameworks
+ and almost anything Eclipse related, but my hope is you will use the
+ examples illustrated here as stepping stones to build your knowledge base.
+ Happy hacking :)</p>
+
+ <h3>Example Downloads</h3>
+
+ <ul>
+ <li><a href="files/shapesemf.zip">Shapes EMF</a></li>
+
+ <li><a href="files/shapesrcp.zip">Shapes RCP</a></li>
+
+ <li><a href="files/shapesmerlin.zip">Shapes Merlin</a></li>
+ </ul>
+
+
+ <h2>Acknowledgments</h2>
+
+ <p>I'd like to thank:</p>
+
+ <ul>
+ <li>Richard Gronback for information regarding GMF.</li>
+
+ <li>Joel Cheuoua for various corrections regarding Merlin and updating my
+ Merlin example.</li>
+
+ <li>Ed Merks for half the posts on the EMF newsgroup, his screenshot and
+ for his feedback on this article.</li>
+
+ <li>Sushma Patel for reviewing the article and correcting my horrible
+ grammar.</li>
+ </ul>
+
+
+ <h2>Bibliography</h2>
+
+ <p>[1] <a name="EMFOverview" href=
+ "http://eclipse.org/emf/docs.php?doc=references/overview/EMF.html">The
+ Eclipse Modeling Framework (EMF) Overview</a>, EMF Website</p>
+
+ <p>[2] <a name="ShapeArticle" href=
+ "http://www.eclipse.org/articles/Article-GEF-diagram-editor/shape.html">A
+ Shape Diagram Editor</a>, Eclipse Corner Article</p>
+
+ <p>[3] <a name="EMFDocumentation" href=
+ "http://www.eclipse.org/emf/docs.php">EMF Documentation</a>, EMF
+ Website</p>
+
+ <p>[4] <a name="EMFTutorial" href=
+ "http://eclipse.org/emf/docs.php?doc=tutorials/clibmod/clibmod.html">Generating
+ an EMF Model</a>, EMF Website</p>
+
+ <p>[5] <a name="CommandStackBug1" href=
+ "https://bugs.eclipse.org/bugs/show_bug.cgi?id=29939">Eclipse Bug
+ #29939</a>, Eclipse Bugzilla</p>
+
+ <p>[6] <a name="CommandStackBug2" href=
+ "https://bugs.eclipse.org/bugs/show_bug.cgi?id=37716">Eclipse Bug
+ #37716</a>, Eclipse Bugzilla</p>
+
+ <p>[7] <a name="CommonCommand" href=
+ "http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.core.commands/">org.eclipse.core.commands</a>,
+ Eclipse CVS</p>
+
+ <p>[8] <a name="GMFWebpage" href="http://www.eclipse.org/gmf">GMF
+ Homepage</a>, GMF Website</p>
+
+ <p>[9] <a name="MerlinWebpage" href=
+ "http://sourceforge.net/projects/merlingenerator/">Merlin Homepage</a>,
+ Merlin Website</p>
+
+ <p>[10] <a name="EDiagramCVSOldProperties" href=
+ "http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.gef.examples.ediagram/src/org/eclipse/gef/examples/ediagram/model/properties/emf/?cvsroot=Tools_Project&amp;only_with_tag=oldProperties">
+ EDiagram Old Properties Source</a>, GEF CVS</p>
+
+ <p>[11] <a name="EDiagramCVS" href=
+ "http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.gef.examples.ediagram/?cvsroot=Tools_Project">
+ EDiagram Example Source</a>, GEF CVS</p>
+
+ <p>[12] <a name="GMFRequirements" href=
+ "http://www.eclipse.org/gmf/requirements.html">GMF Requirements</a>, GMF
+ Website</p>
+
+ <p><small>ref: <a href=
+ "https://bugs.eclipse.org/bugs/show_bug.cgi?id=91472">bug
+ 91472</a></small></p>
+
+ <p><small>Java and all Java-based trademarks and logos are trademarks or
+ registered trademarks of Sun Microsystems, Inc. in the United States, other
+ countries, or both.</small></p>
+ </body>
+</html>
+
diff --git a/Article-GEF-EMF/images/connection.png b/Article-GEF-EMF/images/connection.png
new file mode 100644
index 0000000..fd523d7
--- /dev/null
+++ b/Article-GEF-EMF/images/connection.png
Binary files differ
diff --git a/Article-GEF-EMF/images/ediagram.jpg b/Article-GEF-EMF/images/ediagram.jpg
new file mode 100644
index 0000000..9a57270
--- /dev/null
+++ b/Article-GEF-EMF/images/ediagram.jpg
Binary files differ
diff --git a/Article-GEF-EMF/images/shape.png b/Article-GEF-EMF/images/shape.png
new file mode 100644
index 0000000..48e51f4
--- /dev/null
+++ b/Article-GEF-EMF/images/shape.png
Binary files differ
diff --git a/Article-GEF-EMF/images/shapesdiagram.png b/Article-GEF-EMF/images/shapesdiagram.png
new file mode 100644
index 0000000..76ca051
--- /dev/null
+++ b/Article-GEF-EMF/images/shapesdiagram.png
Binary files differ
diff --git a/Article-GEF-EMF/images/shapesmerlin.png b/Article-GEF-EMF/images/shapesmerlin.png
new file mode 100644
index 0000000..3f33c7e
--- /dev/null
+++ b/Article-GEF-EMF/images/shapesmerlin.png
Binary files differ
diff --git a/Article-GEF-EMF/images/shapesmodel.png b/Article-GEF-EMF/images/shapesmodel.png
new file mode 100644
index 0000000..cc3c68a
--- /dev/null
+++ b/Article-GEF-EMF/images/shapesmodel.png
Binary files differ
diff --git a/Article-GEF-EMF/images/shapesrcp.png b/Article-GEF-EMF/images/shapesrcp.png
new file mode 100644
index 0000000..fd845cf
--- /dev/null
+++ b/Article-GEF-EMF/images/shapesrcp.png
Binary files differ
diff --git a/Article-GEF-EMF/images/shapetypes.png b/Article-GEF-EMF/images/shapetypes.png
new file mode 100644
index 0000000..8779a85
--- /dev/null
+++ b/Article-GEF-EMF/images/shapetypes.png
Binary files differ
diff --git a/Article-GEF-diagram-editor/default_style.css b/Article-GEF-diagram-editor/default_style.css
new file mode 100644
index 0000000..1213bf0
--- /dev/null
+++ b/Article-GEF-diagram-editor/default_style.css
@@ -0,0 +1,49 @@
+p, table, td, th { font-family: arial, helvetica, geneva; font-size: 10pt}
+pre { font-family: "Courier New", Courier, mono; font-size: 10pt}
+h2 { font-family: arial, helvetica, geneva; font-size: 18pt; font-weight: bold ; line-height: 14px}
+code { font-family: "Courier New", Courier, mono; font-size: 10pt}
+sup { font-family: arial,helvetica,geneva; font-size: 10px}
+h3 { font-family: arial, helvetica, geneva; font-size: 14pt; font-weight: bold}
+li { font-family: arial, helvetica, geneva; font-size: 10pt}
+h1 { font-family: arial, helvetica, geneva; font-size: 28px; font-weight: bold}
+body {
+ font-family: arial, helvetica, geneva;
+ font-size: 10pt;
+ clip: rect( );
+ margin-top: 5mm;
+ margin-left: 3mm
+}
+.indextop { font-size: x-large;; font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold}
+.indexsub { font-size: xx-small;; font-family: Arial, Helvetica, sans-serif; color: #8080FF}
+
+div.figure {
+}
+
+div.figure-caption {
+ text-align: center;
+}
+
+span.figure-number {
+ font-weight: bold;
+}
+
+pre.program {
+ margin-left: 1em;
+ margin-right: 1em;
+ padding: 5px;
+ background-color: whitesmoke;
+}
+
+dt {
+ font-weight: bold;
+ margin-left: 2ex;
+}
+
+dd {
+ margin-left: 5ex;
+}
+
+a.cite {
+ text-decoration: none;
+ background-color: whitesmoke;
+}
diff --git a/Article-GEF-diagram-editor/images/Idea.jpg b/Article-GEF-diagram-editor/images/Idea.jpg
new file mode 100644
index 0000000..119ce70
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/Idea.jpg
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/delete_action3.gif b/Article-GEF-diagram-editor/images/delete_action3.gif
new file mode 100644
index 0000000..3dba96b
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/delete_action3.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/linux_only.gif b/Article-GEF-diagram-editor/images/linux_only.gif
new file mode 100644
index 0000000..7c135cf
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/linux_only.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/shape_screenshot2.jpg b/Article-GEF-diagram-editor/images/shape_screenshot2.jpg
new file mode 100644
index 0000000..b2f423c
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/shape_screenshot2.jpg
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/tag_1.gif b/Article-GEF-diagram-editor/images/tag_1.gif
new file mode 100644
index 0000000..4859d6f
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/tag_1.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/tag_2.gif b/Article-GEF-diagram-editor/images/tag_2.gif
new file mode 100644
index 0000000..5ea43dc
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/tag_2.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/tag_3.gif b/Article-GEF-diagram-editor/images/tag_3.gif
new file mode 100644
index 0000000..a69b68e
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/tag_3.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/tag_4.gif b/Article-GEF-diagram-editor/images/tag_4.gif
new file mode 100644
index 0000000..a1ad63f
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/tag_4.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/tag_5.gif b/Article-GEF-diagram-editor/images/tag_5.gif
new file mode 100644
index 0000000..d86a748
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/tag_5.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/tag_6.gif b/Article-GEF-diagram-editor/images/tag_6.gif
new file mode 100644
index 0000000..b9eb4ec
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/tag_6.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/tag_7.gif b/Article-GEF-diagram-editor/images/tag_7.gif
new file mode 100644
index 0000000..5f0e8fa
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/tag_7.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/tip.gif b/Article-GEF-diagram-editor/images/tip.gif
new file mode 100644
index 0000000..77b2451
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/tip.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/tryit.gif b/Article-GEF-diagram-editor/images/tryit.gif
new file mode 100644
index 0000000..f4927a4
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/tryit.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/images/win_only.gif b/Article-GEF-diagram-editor/images/win_only.gif
new file mode 100644
index 0000000..895f9ca
--- /dev/null
+++ b/Article-GEF-diagram-editor/images/win_only.gif
Binary files differ
diff --git a/Article-GEF-diagram-editor/shape.html b/Article-GEF-diagram-editor/shape.html
new file mode 100644
index 0000000..4563849
--- /dev/null
+++ b/Article-GEF-diagram-editor/shape.html
@@ -0,0 +1,1289 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html lang="en">
+<head>
+ <title>A Shape Diagram Editor</title>
+ <link rel="stylesheet" href="default_style.css">
+ <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
+ <meta name="author" content="Bo Majewski">
+</head>
+
+<body>
+<div align="right">
+ &nbsp; <span style="font-family:Times New Roman, Times, serif; font-size: small;">Copyright &copy; 2004 Cisco Systems Inc.</span>
+ <table border="0" cellspacing="0" cellpadding="2" width="100%">
+ <tbody>
+ <tr>
+ <td align="left" valign="top" colspan="2" bgcolor="#0080C0">
+ <span style="font-family: Arial,Helvetica; font-weight: bold; color: #ffffff;">&nbsp;Eclipse
+ Corner Article</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+<div align="left">
+ <h1><img src="images/Idea.jpg" height=86 width=120 align="middle" alt="tag"></h1>
+</div>
+<p>&nbsp;</p>
+
+<h1 align="center">A Shape Diagram Editor</h1>
+
+<blockquote>
+ <b>Summary</b>
+ <br>
+ <p> Graphical Editing Framework (GEF) provides a powerful foundation for creating
+ editors for visual editing of arbitrary models. Its effectiveness lies in
+ a modular build, fitting use of design patterns, and decoupling of components
+ that comprise a full, working editor. To a newcomer, the sheer number and
+ variety of concepts and techniques present in GEF may feel intimidating. However,
+ once learned and correctly used, they help to develop highly scalable and
+ easy to maintain software. This article aims to provide a gentle yet comprehensive
+ introduction to GEF. It describes a shape diagram editor - a small, fully
+ functional test case of core concepts. </p>
+
+ <p>
+ <b> By Bo Majewski, Cisco Systems, Inc.</b>
+ <br>
+ <font size="-1">December 8, 2004</font> </p>
+</blockquote>
+
+<hr width="100%">
+
+<h2>Introduction</h2>
+
+<p> <a href="http://www.eclipse.org/gef/">Graphical Editing Framework</a> (GEF)
+ has been designed to allow editing of user data, generally referred to as <em>the
+ model</em>, using graphical rather than textual format. It becomes an invaluable
+ tool when dealing with entities that contain many-to-many, one-to-many and other
+ complex relationships. With the popularity of the Eclipse <a href="../Article-RCP-1/tutorial1.html">Rich
+ Client Platform</a>, which leads to development of editors for more than just
+ code, the importance of GEF is certain to increase. A few existing examples,
+ such as database schema editor <a class="cite" href="#zoio">[7]</a>, logical
+ circuits editor, and a task flow manager nicely illustrate both the power and
+ flexibility of the framework that may be applied to such varied and disparate
+ domains. </p>
+
+<p> Yet the trouble with any generic framework, and GEF is no exception, is that
+ its comprehensive design makes it hard to learn. Until recently, the smallest
+ available example came with over 75 classes. Trying to understand nuances of
+ GEF from interaction of that many user defined types and hundreds more native
+ to GEF is certain to test the patience and acumen of even the most diligent
+ developers. To rectify this issue, a new, much smaller example editor has been
+ added and will appear in the upcoming 3.1 release. The shape diagram editor
+ (see <a href="#fig1">Figure&nbsp;1</a>) allows you to create and edit simple
+ diagrams. It manipulates two types of objects, represented by rectangles and
+ ellipses. You may connect any two objects with one of the two connection types.
+ The two connection types are represented by solid and dashed lines. Each connection
+ is directed, in the sense that it starts at a source object and terminates in
+ the target object. The direction of each connection is indicated by an arrow.
+ A connection may be reattached by dragging its source or target to a new object.
+ Objects in the editor may be selected either by clicking on them or by dragging
+ a rubber band around them. Selected objects can be deleted. All model manipulations,
+ such as adding or deleting objects, moving them, resizing them, etc., may be
+ undone or redone. Finally, the editor integrates with the <em>Properties</em>
+ and <em>Outline</em> standard views of Eclipse. The editor's virtue comes not
+ from its usefulness, but rather from the fact its limited number of user defined
+ types serve as examples of a large percentage of concepts and techniques that
+ one could encounter in a mature GEF editor. </p>
+
+<a name="fig1"></a>
+<div class="figure">
+<center style="margin-bottom: 1em;">
+ <img src="images/shape_screenshot2.jpg" alt="Screen shot of the diagram editor" width="673" height="464">
+</center>
+<div class="figure-caption">
+ <span class="figure-number">Fig 1</span>. The shape diagram editor running under Linux
+</div>
+</div>
+
+<p>
+ <img src="images/tryit.gif" alt="Try it!" align="middle"> Download and unzip
+ the latest 3.1 GEF Examples from the
+ <a href="http://download.eclipse.org/tools/gef/downloads/">GEF Project
+ Downloads</a>
+ into your main Eclipse directory. To create
+ a new diagram, launch the wizard by pressing <em>Ctrl-N</em>. Expand the
+ <em>Examples</em> folder and select <em>Shapes Diagram</em>. The following
+ sections give a detailed overview of the shape diagram inner workings. Before
+ we dive into code, let us start with a big picture tour of the main
+ GEF ideas.
+</p>
+
+
+<h2>Core GEF concepts</h2>
+
+<p> GEF assists you in building a visual editor of your data. The data may be
+ as simple as a thermostat with a single temperature knob, or as complex as a
+ virtual private network with hundreds of routers, connections, and quality of
+ service policies. To the credit of the GEF designers, they managed to create
+ a framework that works with any data, or in GEF terminology, with any <b>model</b>.
+ This is achieved by strictly following the Model-View-Controller pattern. The
+ model is your data. To GEF, a model is any plain old Java object. The model
+ should not know anything about either the controller or the view. The <b>view</b>
+ is the visual representation of the model or one of its parts on the screen.
+ It may be as simple as a rectangle, line or ellipse, or as complex as a nested
+ logical circuit. Again, the view should remain ignorant about both the model
+ and the controller. GEF uses Draw2D figures as views, although anything that
+ implements the <code>IFigure</code> interface will do. The controller, known
+ as an <b>edit part</b>, is the one that brings the two together. A top level
+ controller is created when you start editing your model. If the model consists
+ of many fragments, the top level controller informs GEF about that fact. In
+ turn, child controllers for each fragment are created. If those again consists
+ of subparts, the process is repeated until all objects that comprise a model
+ have their controllers built. The other task of the controller is to create
+ a figure representing the model. Once the model has been set on a particular
+ controller, the GEF asks it for the congruous <code>IFigure</code> object. Since
+ neither the model nor the view know about each other, it is the task of the
+ controller to listen to changes in the model and update the visual representation
+ of it. As a result, a common pattern in many GEF editors is a model that posts
+ <code>PropertyChangeEvent</code> notifications. When an edit part receives an
+ event notification it reacts appropriately by adjusting visual or structural
+ representation of the model. </p>
+<p>
+ Another aspect of visual editing is reacting to user actions and mouse
+ or keyboard events. The challenge here is to provide a mechanism that
+ comes with sensible defaults, yet at the same time is flexible enough to
+ allow those defaults to be replaced by interactions appropriate for
+ the edited model. Take a mouse drag event as an example. If we were
+ to assume every time a mouse drag event is detected that all selected
+ objects are moved, we'd limit the freedom of the editor developer. It
+ is quite likely that somebody might wish to provide zoom in or out
+ operations on a mouse being dragged. GEF solves this issue by using
+ tools, requests, and policies.
+</p>
+<p>
+ A <b>tool</b> is a stateful object that translates low level events,
+ such as mouse pressed, mouse dragged, and so on, into high level
+ <b>requests</b>, represented by a <code>Request</code> object.
+ Which request is posted depends on which tool is active. For example,
+ the connection tool, upon receiving a mouse pressed event, posts a
+ connection start or connection end request. If it was a create tool,
+ we'd receive a create request. GEF comes with a number
+ of predefined tools and means of creating application specific
+ tools. Tools may be activated programmatically or as a response to a
+ user action. Most of the time, tools post requests to the <code>EditPart</code>
+ whose figure was underneath the mouse. For example, if you click on a rectangle
+ representing a widget, the edit part associated with it receives a
+ selection or direct edit request. Sometimes, like the <code>MarqueeSelectionTool</code>
+ does, the request
+ is posted to all parts whose figures are contained within a given area. Regardless of
+ how one or more edit parts are chosen as the target of requests,
+ they do not handle requests themselves. Instead, they delegate this
+ task to registered <b>edit policies</b>. Each policy is asked for a command
+ for a given request. A policy not wishing to handle the request may
+ return a <code>null</code>. The mechanism of having policies
+ rather than an edit part respond
+ to requests allows to keep both of them small
+ and highly specialized. This, in turn, means easy to debug and more
+ maintainable code.
+ The final piece of the puzzle is <b>commands</b>. Rather than
+ modifying the model directly, GEF requires that you do it with the help of
+ commands. Each command should implement applying and undoing
+ changes to the model or its part. This way GEF editors automatically
+ support the undo/redo of model alterations.
+</p>
+
+<p>
+ A significant benefit of using GEF, in addition to being able to boast about
+ your skills and design pattern knowledge, is the fact that it fully
+ integrates with the Eclipse platform. Objects selected in the editor
+ may provide properties for the standard <em>Properties</em> view. Eclipse wizards
+ may be used to create and initialize models edited by GEF editors. <em>Undo</em>
+ and <em>Redo</em> items of the <em>Edit</em> menu may trigger undoing or redoing of
+ GEF editing changes. Simply put, GEF editors are first class citizens
+ of the regular Eclipse platform, with the same level of integration as
+ a text editor or any other workbench editor, implementing <code>IEditorPart</code>
+ interface.
+
+
+<h2>The Model</h2>
+
+<p>
+ The first step when building a GEF editor is to create a model. In our case
+ the model consists of four types of objects: a shape diagram, which holds shapes,
+ two shape types, and shape connections.
+ Before we start writing code for those classes, we prepare some
+ basic infrastructure.
+</p>
+
+<h3>Core model classes</h3>
+<p>
+ When creating a model use the following guidelines:
+</p>
+<ul>
+ <li>
+ <b>The model stores all data that may be edited or viewed by
+ the user</b>. In particular, this also means data pertinent to the
+ visual representation, such as bounds. You may not rely on either
+ edit parts or figures to keep such data, as they may be created and
+ discarded at will. If you dislike storing visual data together with
+ your business data, consider the suggestion made in
+ <a class="cite" href="#hudson">[3]</a>.
+ </li>
+ <li>
+ <b>Provide ways of persisting the model</b>. Ensure that when an
+ editor is closed your model is persisted. When the same editor is
+ opened, implement a method for the model to restore its state from
+ permanent storage.
+ </li>
+ <li>
+ <b>The model must remain ignorant of the view or the
+ controller</b>. Never store any references to either the view or
+ the controller. GEF may discard a view or a controller under certain
+ circumstances. If you keep references to them, you are left with
+ an inactive figure or an edit part.
+ </li>
+ <li><b>Provide a way for others to listen to changes in your
+ model</b>. This allows the
+ controller to react to changes and appropriately adjust the
+ view. Since you are not allowed to keep a reference to the controller,
+ the only way to deal with it is to provide a way for a controller to
+ register (and unregister!) with your model as a receiver of events. A
+ good choice is a property change event notification defined in the
+ <code>java.beans</code> package.
+ </li>
+</ul>
+
+<p>
+ As the above outlined rules are common for all models, it is beneficial
+ to create a hierarchy of base classes that enforces them. The
+ <code>ModelElement</code> extends Java's <code>Object</code> class, adding
+ three features: persistence, property change, and property source support.
+ Simple model persistence is guaranteed by implementing
+ <img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> the
+ <code>java.io.Serializable</code> interface together with
+ <img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag"> the
+ <code>readObject</code> method. This solution permits one to save the
+ editor's model in a binary
+ format. While it may work for certain applications, it does not provide
+ format portability. In more complex cases, one may implement
+ saving the model in XML or similar format. Model changes are communicated
+ using property change events. The base class allows edit parts to
+ <img src="images/tag_4.gif" height=13 width=24 align="middle" alt="tag">
+ register and
+ <img src="images/tag_5.gif" height=13 width=24 align="middle" alt="tag">
+ unregister as receivers of property change notifications.
+ Those are posted by calling
+ <img src="images/tag_6.gif" height=13 width=24 align="middle" alt="tag">
+ the <code>firePropertyChange</code> method.
+ Finally, in order to aid integration with the <em>Properties</em> view of the workbench,
+ <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag">
+ the <code>IPropertySource</code> interface is implemented (details of which
+ are omitted in Figure&nbsp;2).
+</p>
+
+<div class="figure">
+<pre class="program">public abstract class ModelElement implements <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag"> IPropertySource, <img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> Serializable {
+
+ private transient PropertyChangeSupport pcsDelegate =
+ new PropertyChangeSupport(this);
+
+<img src="images/tag_4.gif" height=13 width=24 align="middle" alt="tag"> public synchronized void addPropertyChangeListener(PropertyChangeListener l) {
+ if (l == null) {
+ throw new IllegalArgumentException();
+ }
+
+ pcsDelegate.addPropertyChangeListener(l);
+ }
+
+<img src="images/tag_6.gif" height=13 width=24 align="middle" alt="tag"> protected void firePropertyChange(String property,
+ Object oldValue,
+ Object newValue) {
+ if (pcsDelegate.hasListeners(property)) {
+ pcsDelegate.firePropertyChange(property, oldValue, newValue);
+ }
+ }
+
+<img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag"> private void readObject(ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+ in.defaultReadObject();
+ pcsDelegate = new PropertyChangeSupport(this);
+ }
+
+<img src="images/tag_5.gif" height=13 width=24 align="middle" alt="tag"> public synchronized void removePropertyChangeListener(PropertyChangeListener l) {
+ if (l != null) {
+ pcsDelegate.removePropertyChangeListener(l);
+ }
+ }
+
+ ...
+}</pre>
+<div class="figure-caption">
+ <span class="figure-number">Fig 2</span>. The base class of all model objects
+</div>
+</div>
+
+<p>
+ Two types of objects, ellipse and rectangle shapes, share further common
+ functionality that may be factored out into a common class. In particular,
+ both represent objects that occupy certain locations and have a non-zero
+ size. Both may have connections ending or originating at them. Any changes
+ to these properties need to be communicated to all listeners. Furthermore,
+ the location and size property are also exposed through the
+ <code>IPropertySource</code> interface, allowing the user to inspect and
+ modify them via the <em>Properties</em> view.
+</p>
+
+<p>
+ Management of connections between objects is worth a more detailed look.
+ There is no concept of a global store of all connections. Instead, GEF
+ requires model parts to report any connections that start
+ or terminate in them. These must be reported as <code>Lists</code>
+ of objects. The <code>Shape</code> class maintains two array lists
+ of <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag">
+ source and
+ <img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag">
+ target connections. The source connections are those
+ which have the given shape as the source, and target connections
+ are those in which the given shape is recorded as the target. Two
+ methods
+ (<img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag">,
+ <img src="images/tag_4.gif" height=13 width=24 align="middle" alt="tag">),
+ with package level visibility, are added that allow shapes
+ and connections to communicate about their mutual relationship. In
+ addition, two public methods
+ (<img src="images/tag_5.gif" height=13 width=24 align="middle" alt="tag">,
+ <img src="images/tag_6.gif" height=13 width=24 align="middle" alt="tag">)
+ are defined that allow classes external
+ to the <code>model</code> package learn about connectivity of a shape.
+ These are used by shape controllers, explained in the subsequent part
+ of this article.
+</p>
+
+<div class="figure">
+<pre class="program">public abstract class Shape extends ModelElement {
+
+ private Point location = new Point(0, 0);
+ private Dimension size = new Dimension(50, 50);
+<img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag"> private List sourceConnections = new ArrayList();
+<img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> private List targetConnections = new ArrayList();
+
+ public Point getLocation() {
+ return location.getCopy();
+ }
+
+ public void setLocation(Point newLocation) {
+ if (newLocation == null) {
+ throw new IllegalArgumentException();
+ }
+ location.setLocation(newLocation);
+ firePropertyChange(LOCATION_PROP, null, location);
+ }
+
+<img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag"> void addConnection(Connection conn) {
+ if (conn == null || conn.getSource() == conn.getTarget()) {
+ throw new IllegalArgumentException();
+ }
+ if (conn.getSource() == this) {
+ sourceConnections.add(conn);
+ firePropertyChange(SOURCE_CONNECTIONS_PROP, null, conn);
+ } else if (conn.getTarget() == this) {
+ targetConnections.add(conn);
+ firePropertyChange(TARGET_CONNECTIONS_PROP, null, conn);
+ }
+ }
+
+<img src="images/tag_4.gif" height=13 width=24 align="middle" alt="tag"> void removeConnection(Connection conn) {
+ if (conn == null) {
+ throw new IllegalArgumentException();
+ }
+ if (conn.getSource() == this) {
+ sourceConnections.remove(conn);
+ firePropertyChange(SOURCE_CONNECTIONS_PROP, null, conn);
+ } else if (conn.getTarget() == this) {
+ targetConnections.remove(conn);
+ firePropertyChange(TARGET_CONNECTIONS_PROP, null, conn);
+ }
+ }
+
+<img src="images/tag_5.gif" height=13 width=24 align="middle" alt="tag"> public List getSourceConnections() {
+ return new ArrayList(sourceConnections);
+ }
+
+<img src="images/tag_6.gif" height=13 width=24 align="middle" alt="tag"> public List getTargetConnections() {
+ return new ArrayList(targetConnections);
+ }
+
+ ...
+}</pre>
+<div class="figure-caption">
+ <span class="figure-number">Fig 3</span> Shape functionality
+</div>
+</div>
+
+
+<h3>Top level model classes</h3>
+
+<p>
+ With the above preparation we may start coding top level model classes.
+ The <code>Connection</code> class represents a connection between two
+ shapes. It stores the source and target of a connection. Changes in
+ connectivity are effected by invoking <code>disconnect</code> or
+ <code>reconnect</code> methods. Connections maintain a boolean
+ flag indicating if they are currently connected or disconnected.
+ The flag is used by commands to verify legitimacy of certain
+ operations. Both source and target retain
+ references to the original shapes allowing disconnected connections
+ to be easily reconnected. Connections maintain one attribute,
+ the line style. The <code>EllipticalShape</code> and
+ <code>RectangularShape</code> classes
+ provide an extension to the above described <code>Shape</code>
+ class, with a minimum of functionality added.
+</p>
+
+<p>
+ The <code>ShapeDiagram</code> class extends the <code>ModelElement</code>
+ class with the container functionality. It maintains a collection of
+ shapes and notifies listeners about collection changes. The boolean values
+ returned by <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag">
+ the <code>addChild</code> and
+ <img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag">
+ <code>removeChild</code> methods
+ are used by commands to perform validation of their operations. Public access to all
+ shapes in a diagram is <img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag">
+ provided for the benefit of the controller class.
+</p>
+
+<div class="figure">
+<pre class="program">public class ShapesDiagram extends ModelElement {
+
+ ...
+ private Collection shapes = new Vector();
+
+<img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag"> public boolean addChild(Shape s) {
+ if (s != null && shapes.add(s)) {
+ firePropertyChange(CHILD_ADDED_PROP, null, s);
+ return true;
+ }
+ return false;
+ }
+
+<img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag"> public List getChildren() {
+ return new Vector(shapes);
+ }
+
+<img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> public boolean removeChild(Shape s) {
+ if (s != null && shapes.remove(s)) {
+ firePropertyChange(CHILD_REMOVED_PROP, null, s);
+ return true;
+ }
+ return false;
+ }
+}</pre>
+<div class="figure-caption">
+ <span class="figure-number">Fig 4</span>. <code>ShapeDiagram</code> - a container
+ of shapes
+</div>
+</div>
+
+<h3>A note on implementation</h3>
+<p>
+ A careful reader is certain to recognize that the model effectively
+ created a specific implementation
+ of a directed graph, with shapes acting as vertices, connections
+ representing edges, and shape diagrams playing the role of the graph. The
+ representation built here is known as adjacency list representation
+ and is suitable for sparse graphs. With minimal effort, one could
+ transform the model's code into a generic graph representation. The only additions to
+ the implementation regularly presented in books on algorithms is the
+ fact that the graph, its nodes, and its edges post events when their
+ states change. Also nodes, unlike in mathematical graphs, rather than
+ being zero-dimensional points, have rectangular bounds. Finally, while
+ regular graphs act as a central global storage of edges, a diagram does not
+ hold connections, as GEF does not require it.
+</p>
+<p>
+ It is worth noting that the solutions employed by the above presented classes
+ are not the only ones possible. Those who developed computer representations
+ of graphs may prefer alternative ways of storing connections
+ or arranging communications between nodes and edges. However, such
+ details are not important. Designers are free to choose their own more
+ generic, faster, or otherwise enhanced model representation. The vital part is
+ event based notification of model changes, maintenance of all, including
+ visual attributes of the model, and support for model persistence.
+ Depending on your experience and needs, the rest are traits which you should
+ feel free to alter.
+</p>
+
+<h2>The Views</h2>
+
+<p>
+ Due to the simplicity of the shape diagram editor, we do not have to create figures
+ representing our model, but use predefined figures instead. A
+ diagram is represented by the <code>Figure</code> class equipped with the
+ <code>FreeformLayout</code> manager. This gives
+ us the freedom to drag and drop objects at any location. Objects
+ are represented either by the <code>RectangleFigure</code> or
+ by <code>Ellipse</code>. Relying on predefined figures to represent parts of
+ the model is uncustomary. Even though your view may not have any
+ references to either the model or the controller, it must have a
+ visual attribute for every important aspect of the model that the
+ user may wish to inspect or change. It is thus much more common
+ to define intricate figures with the number of visual attributes,
+ such as color, text, nested figures, etc., matching the number
+ of attributes of the model they represent. For a more
+ thorough treatment about creating complex figures please see
+ <a class="cite" href="#lee">[4]</a>.
+</p>
+
+<h2>The Parts</h2>
+
+<p>
+ For each independent piece of the model we must define a controller. By
+ "independent" we mean an element that may be subject to user
+ manipulations. A good rule of thumb to follow is that anything that
+ may be selected or deleted should have its own edit part.
+</p>
+<p>
+ The role of edit parts is to understand the model, listen to events about
+ its changes, and update views, correspondingly. Due to the choices made
+ at the model level, all edit parts follow the pattern shown in
+ Figure&nbsp;5. Each part <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag">
+ implements the <code>PropertyChangeListener</code>
+ interface. When <img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag">
+ activated, it registers with the model as the receiver of
+ the property change events. Upon
+ <img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag">
+ deactivation, it removes itself from the
+ list of listeners. Finally, when it
+ <img src="images/tag_4.gif" height=13 width=24 align="middle" alt="tag">
+ receives a property change event, based
+ on the name of the property and the new and old values it refreshes one
+ or more visual aspects of the figure representing the model. In fact, this
+ pattern is so common that in a larger application it would justify creating
+ a base class factoring out this behavior.
+</p>
+<div class="figure">
+<pre class="program">public abstract class SpecificPart extends AbstractGraphicalEditPart
+<img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag"> implements PropertyChangeListener {
+
+<img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> public void activate() {
+ if (!isActive()) {
+ super.activate();
+ ((PropertyAwareModel) this.getModel()).addPropertyChangeListener(this);
+ }
+ }
+
+<img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag"> public void deactivate() {
+ if (isActive()) {
+ ((PropertyAwareModel) this.getModel()).removePropertyChangeListener(this);
+ super.deactivate();
+ }
+ }
+
+<img src="images/tag_4.gif" height=13 width=24 align="middle" alt="tag"> public void propertyChage(PropertyChangeEvent evt) {
+ String prop = evt.getPropertyName();
+ ...
+ }
+}</pre>
+<div class="figure-caption">
+ <span class="figure-number">Fig 5</span>. Property aware part
+</div>
+</div>
+
+<h3>The <tt>DiagramEditPart</tt> class</h3>
+
+<p>
+ When the editor successfully loads and sets a shape diagram object on a
+ graphical viewer, the <code>ShapesEditPartFactory</code> is asked to
+ create a part controlling the diagram. It creates a new <code>DiagramEditPart</code>
+ and sets the diagram as its model. The newly created part is activated,
+ registers itself with the model, and creates a figure, with a free form layout
+ manager that allows positioning of diagram figures based on their constraints
+ (bounds). The <code>DiagramEditPart</code> reports all shapes contained
+ in the diagram via the <code>getModelChildren</code>. As mentioned before,
+ GEF repeats the process of generating parts and figures for all returned
+ model children.
+</p>
+
+<p>
+ The <code>DiagramEditPart</code> class installs three policies. All policies
+ should be installed in the <code>createEditPolicies</code> method that
+ is declared by the <code>AbstractEditPart</code> class, and must be implemented
+ by all concrete classes extending the <code>AbstractGraphicalEditPart</code>.
+ Policies are delegates used by edit parts to handle requests posted by
+ tools. In the simplest cases, policies take care of generating
+ commands. A policy is registered with the <code>String</code> key, referred
+ to as the policy's role.
+ The key has no meaning to edit parts. However, it should have meaning to a software
+ developer, as it allows others, specifically those who extend your
+ controller, to disable or remove the policy by specifying its key. As far
+ as GEF is concerned, your key could be <code>"foobar"</code>. However,
+ you'd better tell your fellow developers that in order to, say, set a new
+ layout policy when the layout manager is changed, they need to
+ install a new <code>"foobar"</code> policy. As this might be amusing, but not
+ obvious, it is recommended that you use keys defined in
+ the <code>EditPolicy</code> interface, whose names
+ try to convey the role the given policy plays in an edit part.
+</p>
+<p>
+ The <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag">
+ first policy installed using the <code>EditPolicy.COMPONENT_ROLE</code> key
+ has the task of preventing the root of the model from being deleted. It overrides
+ the <code>createDeleteCommand</code> method to return an unexecutable
+ command. The <img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag">
+ second policy, installed with the <code>LAYOUT_ROLE</code>
+ key, handles create and constraint change requests. The first request is
+ posted when a new shape is dropped into a diagram. The layout policy
+ returns a command that adds a new shape to the diagram editor and places
+ it at the drop location. The constraint change request is posted whenever
+ the user resizes or moves shapes already present in the diagram. The
+ <img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag">
+ third call to the <code>installEditPolicy</code> removes rather than
+ installs a policy. This prevents the root part from providing selection
+ feedback when the user clicks on the area of the diagram corresponding
+ to the root of the model. This call also illustrates the importance of
+ meaningful keys used to register part's policies.
+</p>
+
+<div class="figure">
+<pre class="program">protected void createEditPolicies() {
+<img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag"> installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy());
+ XYLayout layout = (XYLayout) getContentPane().getLayoutManager();
+<img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> installEditPolicy(EditPolicy.LAYOUT_ROLE, new ShapesXYLayoutEditPolicy(layout));
+<img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag"> installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, null);
+}</pre>
+<div class="figure-caption">
+ <span class="figure-number">Fig 6</span>. Policies installed by the diagram
+ edit part.
+</div>
+</div>
+
+<p>
+ The diagram edit part monitors child added and child removed property events.
+ These are posted by the <code>ShapesDiagam</code> class whenever new
+ shapes are added or removed. Upon detecting either type of a property
+ change event, the diagram edit part invokes the <code>refreshChildren</code>
+ method, defined in the <code>AbstractEditPart</code>. This method traverses
+ all model children and creates, removes, or re-orders edit part children
+ appropriately.
+</p>
+
+<h3>The <tt>ShapeEditPart</tt> class</h3>
+
+<p>
+ Diagram shapes are managed by the <code>ShapeEditPart</code>. The part itself
+ is created by the <code>ShapesEditPartFactory</code> in response to
+ <code>DiagramEditPart</code> returning a list of model children. Each
+ part created by the factory is given the child model which it controls.
+ Once the model is set, the part is asked to create a figure representing it.
+ Depending on the type of the model, it returns either an ellipse or a
+ rectangle.
+</p>
+
+<p>
+ Shape edit parts monitor four types of property change events: size,
+ location, source, and target connections. If the shape changes size or location,
+ the <img src="images/tag_6.gif" height=13 width=24 align="middle" alt="tag">
+ <code>refreshVisual</code> method is called. This method is automatically
+ invoked by GEF the first time a figure is created. In it, the visual
+ attributes of the figure should be adjusted based on the state of the
+ model. Reusing the same method for model updates is another frequently
+ encountered pattern in GEF editors. In the case of the shape editor part,
+ the new location and size are fetched and stored with the figure representing
+ the shape. In addition, the new bounds are passed as the constraint to the
+ layout manager of the parent controller. When source or target connections
+ change, the source or target connection edit parts are refreshed by a call
+ to the methods defined in the <code>AbstractGraphicalEditPart</code>.
+ Similarly to the <code>refreshChildren</code> method, these methods go
+ through the list of connections and add, remove, or reposition edit parts
+ corresponding to them.
+</p>
+
+<div class="figure">
+ <pre class="program">class ShapeEditPart extends AbstractGraphicalEditPart
+<img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag"> implements PropertyChangeListener, NodeEditPart {
+
+<img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> protected List getModelSourceConnections() {
+ return getCastedModel().getSourceConnections();
+ }
+
+<img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag"> protected List getModelTargetConnections() {
+ return getCastedModel().getTargetConnections();
+ }
+
+<img src="images/tag_4.gif" height=13 width=24 align="middle" alt="tag"> public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {
+ return new ChopboxAnchor(getFigure());
+ }
+
+<img src="images/tag_5.gif" height=13 width=24 align="middle" alt="tag"> public ConnectionAnchor getSourceConnectionAnchor(Request request) {
+ return new ChopboxAnchor(getFigure());
+ }
+
+ public void propertyChange(PropertyChangeEvent evt) {
+ String prop = evt.getPropertyName();
+
+ if (Shape.SIZE_PROP.equals(prop) || Shape.LOCATION_PROP.equals(prop)) {
+ refreshVisuals();
+ }
+ if (Shape.SOURCE_CONNECTIONS_PROP.equals(prop)) {
+ refreshSourceConnections();
+ }
+ if (Shape.TARGET_CONNECTIONS_PROP.equals(prop)) {
+ refreshTargetConnections();
+ }
+ }
+
+<img src="images/tag_6.gif" height=13 width=24 align="middle" alt="tag"> protected void refreshVisuals() {
+ Rectangle bounds = new Rectangle(getCastedModel().getLocation(),
+ getCastedModel().getSize());
+ figure.setBounds(bounds);
+ ((GraphicalEditPart) getParent()).setLayoutConstraint(this, figure, bounds);
+ }
+}</pre>
+ <div class="figure-caption">
+ <span class="figure-number">Fig 7</span>. Controller of shapes
+ </div>
+</div>
+
+<p>
+ As shapes may be connected to other shapes, the shape edit part overrides the
+ <img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag">
+ <code>getModelSourceConnections</code> and the
+ <img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag">
+ <code>getModelTargetConnections</code> methods. The role of these methods
+ is to inform GEF about connections that originate or terminate at the
+ given shape. In addition, the <code>ShapeEditPart</code> implements
+ the <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag">
+ <code>NodeEditPart</code> interface. By implementing it, the edit part is
+ able to define source and target anchors, i.e., points to which connections
+ attach. The logic circuit editor example uses this feature to indicate
+ where a wire would attach to a logical gate. Since shapes do not have
+ any specific connection points, we use a chop box anchor which clips the
+ connection against the rectangular bounds of the figure. If you wish,
+ you can return the <code>EllipseAnchor</code> for ellipse shapes, which
+ returns a point on the ellipse's boundary. For more complex shapes, you should
+ extend the <code>AbstractConnectionAnchor</code> class and implement the
+ <code>getLocation</code> method. Notice that two types of methods are
+ implemented: one taking a <code>ConnectionEditPart</code>, and one
+ taking a <code>Request</code> as the parameter. The
+ <img src="images/tag_5.gif" height=13 width=24 align="middle" alt="tag">
+ second method is invoked to provide a user with feedback while a new
+ connection is being created. The
+ <img src="images/tag_4.gif" height=13 width=24 align="middle" alt="tag">
+ first one is used for
+ established connections.
+</p>
+
+<p>
+ Shape edit part installs two policies. The <code>ShapeComponentEditPolicy</code>
+ supplies a command for removing a shape from the diagram. The second policy,
+ installed with the <code>GRAPHICAL_NODE_ROLE</code> key, handles the task of
+ creating and reattaching connections between shapes. A new connection is
+ created in two steps by the connection creation tool. When a user clicks on a
+ figure corresponding to an element of the model, the policy is requested to
+ <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag">
+ create a connection command. Returning <code>null</code> from this method
+ indicates that the connection may not originate from the given element of
+ the model. If the connection is possible, a new command should be created and
+ stored in the request as the start command. When another figure is
+ clicked, the policy is required to supply a
+ <img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag">
+ connection complete command. This
+ could be a new command built from the start command, or the start command tag
+ supplied with the information about the terminating point of the connection.
+</p>
+
+<div class="figure">
+ <pre class="program">new GraphicalNodeEditPolicy() {
+<img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag"> protected Command getConnectionCreateCommand(CreateConnectionRequest request) {
+ Shape source = (Shape) getHost().getModel();
+ int style = ((Integer) request.getNewObjectType()).intValue();
+ ConnectionCreateCommand cmd = new ConnectionCreateCommand(source, style);
+ request.setStartCommand(cmd);
+ return cmd;
+ }
+
+<img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> protected Command getConnectionCompleteCommand(CreateConnectionRequest request) {
+ ConnectionCreateCommand cmd =
+ (ConnectionCreateCommand) request.getStartCommand();
+ cmd.setTarget((Shape) getHost().getModel());
+ return cmd;
+ }
+
+ ...
+}</pre>
+ <div class="figure-caption">
+ <span class="figure-number">Fig 8</span>. Graphical node edit policy
+ </div>
+</div>
+
+<p>
+ The other task of the graphical node edit policy is to provide connection
+ reattachment commands. Connection reattachment may change the source or the
+ target of the connection. The same rules apply to these commands as to the
+ connection creation command. In particular, if a given connection should not
+ be reattached, the policy must return null. It is also possible for the policy
+ to return a command that refuses to be executed, by returning false from the
+ <code>canExecute</code> method. Due to space limitation, details of these
+ commands are left out and the reader is referred to the source code.
+</p>
+
+<h3>The <tt>ConnectionEditPart</tt> class</h3>
+
+<p>
+ As connections are user editable parts of the model, they
+ must have their own controller. It is implemented
+ by the <code>ConnectionEditPart</code> class, which extends
+ the <code>AbstractConnectionEditPart</code>
+ class. Similar to other controllers, it implements the
+ <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag">
+ <code>PropertyChangeListener</code> interface
+ and registers the part for the events with the model on activation.
+ The connection part
+ <img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag">
+ returns a polyline decorated with an arrow as the figure.
+ It installs two edit policies. The
+ first one, the <img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag">
+ <code>ConnectionComponentPolicy</code>, supplies
+ a delete command needed by the action associated with the <em>Delete</em>
+ menu item. The <img src="images/tag_4.gif" height=13 width=24 align="middle" alt="tag">
+ second one is of greater interest. It equips
+ a selected connection with handles, placed at the start and the
+ end. Without this policy, reattaching connections
+ is impossible, as the GEF has no handles to grab onto when the
+ end of the connection is being dragged. The authors of the GEF
+ recommend that all <code>ConnectionEditParts</code> should have
+ this policy, even if their ends are not draggable. At minimum this
+ policy provides a visual selection feedback. The
+ <code>propertyChange</code> method watches for
+ <img src="images/tag_5.gif" height=13 width=24 align="middle" alt="tag">
+ changes in the line
+ style property and adjusts the polyline figure appropriately.
+</p>
+
+<div class="figure">
+<pre class="program">class ConnectionEditPart extends AbstractConnectionEditPart
+<img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag"> implements PropertyChangeListener {
+
+ protected IFigure createFigure() {
+<img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> PolylineConnection connection = (PolylineConnection) super.createFigure();
+ connection.setTargetDecoration(new PolygonDecoration());
+ connection.setLineStyle(getCastedModel().getLineStyle());
+ return connection;
+ }
+
+ protected void createEditPolicies() {
+<img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag"> installEditPolicy(EditPolicy.CONNECTION_ROLE, new ConnectionEditPolicy() {
+ protected Command getDeleteCommand(GroupRequest request) {
+ return new ConnectionDeleteCommand(getCastedModel());
+ }
+ });
+<img src="images/tag_4.gif" height=13 width=24 align="middle" alt="tag"> installEditPolicy(EditPolicy.CONNECTION_ENDPOINTS_ROLE,
+ new ConnectionEndpointEditPolicy());
+ }
+
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getPropertyName();
+<img src="images/tag_5.gif" height=13 width=24 align="middle" alt="tag"> if (Connection.LINESTYLE_PROP.equals(property)) {
+ ((PolylineConnection) getFigure()).
+ setLineStyle(getCastedModel().getLineStyle());
+ }
+ }
+ ...
+}</pre>
+<div class="figure-caption">
+ <span class="figure-number">Fig 9</span>. Controller of connections
+</div>
+</div>
+
+
+<h2>Shape Editor</h2>
+
+<p>
+ The shape editor extends the <code>GraphicalEditorWithFlyoutPalette</code>
+ class. This class is a specialized form of a graphical editor, a type
+ of an editor part, equipped with a palette hosting tool entries. The
+ extending class must implement two methods, <code>getPaletteRoot</code>
+ and <code>getPalettePreferences</code>. The first method must return a
+ palette root populated with tool entries. Tool entries are specialized
+ types of palette entries capable of installing tools on the edit
+ domain of the editor. They may be hosted in palette drawers, which
+ provide convenient way of grouping them. It is recommended that
+ one tool entry is set as the default entry of the palette root. A typical
+ solution is to use an instance of the <code>SelectionToolEntry</code>
+ class in that role. Palette preferences, returned by the second method,
+ specify whether the palette is visible or collapsed, the location where it
+ is docked, and the palette width. A commonly found solution is to save them
+ to and restore them from the plug-in's preference store.
+</p>
+
+<p>
+ The already mentioned edit domain plays the role of a central controller. It
+ holds a palette of tools, loads the default tool, maintains the active tool
+ to which it forwards mouse and key events, and deals with the command stack.
+ GEF provides the default implementation, the <code>DefaultEditDomain</code>,
+ which you should set on your editor in the constructor.
+</p>
+
+<p>
+ Part of the job that a graphical editor must perform is to create and
+ initialize a graphical viewer. A graphical viewer is a specialized
+ <code>EditPartViewer</code> capable of performing hit testing. Again, we may
+ rely on the default viewer supplied by the
+ <code>GraphicalEditor</code> class. There are, however, a few things that
+ need to be done. In the <code>configureGraphicalViewer</code> method
+ <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag">
+ set a factory of edit parts. The factory must implement
+ the sole method of the <code>EditPartFactory</code> interface,
+ <code>createEditPart(EditPart, Object)</code>. The first argument is the
+ edit part that returned the second argument, a (part of your) model, through
+ the <code>getModelChildren</code> method. Other things to do here
+ may include setting up a key handler, context menus, etc.
+</p>
+
+<div class="figure">
+<pre class="program">protected void configureGraphicalViewer() {
+ super.configureGraphicalViewer();
+
+ GraphicalViewer viewer = getGraphicalViewer();
+ viewer.setRootEditPart(new ScalableRootEditPart());
+<img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag"> viewer.setEditPartFactory(new ShapesEditPartFactory());
+ viewer.setKeyHandler(
+ new GraphicalViewerKeyHandler(viewer).setParent(getCommonKeyHandler()));
+ ContextMenuProvider cmProvider =
+ new ShapesEditorContextMenuProvider(viewer, getActionRegistry());
+ viewer.setContextMenu(cmProvider);
+ getSite().registerContextMenu(cmProvider, viewer);
+}
+
+protected void initializeGraphicalViewer() {
+ super.initializeGraphicalViewer();
+ GraphicalViewer graphicalViewer = getGraphicalViewer();
+<img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> graphicalViewer.setContents(getModel());
+<img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag"> graphicalViewer.addDropTargetListener(createTransferDropTargetListener());
+}</pre>
+<div class="figure-caption">
+ <span class="figure-number">Fig 10</span>. Configuring and initializing a graphic viewer
+</div>
+</div>
+
+<p>
+ Once the factory is set, you should
+ <img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag">
+ set the contents on the graphical viewer.
+ The contents naturally should be the object restored from the
+ <code>IEditorInput</code> passed to the editor in the <code>setInput</code>
+ method. The shape example also adds
+ <img src="images/tag_3.gif" height=13 width=24 align="middle" alt="tag">
+ a drop target listener to the graphical
+ viewer. This allows one to use the drag and drop gesture rather than select and
+ click when adding new shapes to the diagram. The drop target listener
+ uses a subclassed <code>TemplateTransferDropTargetListener</code> that
+ uses a <code>CreateRequest</code> to fetch a command for adding an
+ object to the model owned by the edit part above which the drag and
+ drop gesture was finalized.
+</p>
+
+<p>
+ In addition to the described tasks, the editor takes care of reporting
+ the dirty flag by monitoring a command stack. This is a preferred
+ solution, as this keeps the flag in synch with any undo or redo
+ actions that the user may perform. Notice that the command stack
+ has the save location marked in both <code>doSave</code> and
+ <code>doSaveAs</code> methods. Other details of the editor, such
+ as actual saving and restoring of the model, are not discussed here
+ as they tend to be very application specific. The editor's functionality
+ that deals with exposing editor content to other views, connecting
+ menu items to editor actions, and other workbench cooperation techniques
+ is described next.
+</p>
+
+<h2>Integrating with the workbench</h2>
+
+<p>
+ The editor, as presented so far, would be fully operational. However,
+ it would not integrate well with the workbench. For example, the
+ <em>Edit</em> menu actions, such as <em>Delete</em>, <em>Undo</em>, and
+ <em>Redo</em> could not be used. Other views could not show alternative
+ presentations of the editor content. In other words, the editor would
+ not get the benefits of being part of the Eclipse workbench. The task
+ of transforming an isolated editor into a proper participant of the
+ workbench is explained in the following three sections.
+</p>
+
+<h3>Editor Actions</h3>
+
+<p>
+ The <code>ShapesEditor</code> class creates a number of default
+ actions in the <code>createActions</code> method invoked during editor
+ initialization. These are undo, redo, select all, delete, save, and print
+ actions. In order to
+ connect standard menu items to them, you should define an action bar
+ contributor and list it, in the <code>plugin.xml</code> file, as
+ the editor contributor. In the action bar contributor you need to
+ implement two methods. The first one,
+ <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag">
+ the <code>buildActions</code> method,
+ should create retargetable actions for undo, redo, and delete. If you
+ wish to enable keyboard selection of all widgets, you need
+ to <img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> add a global
+ action key for the selected action in the second method,
+ <code>declareGlobalActionKeys</code>.
+</p>
+
+<div class="figure">
+ <pre class="program">public class ShapesEditorActionBarContributor extends ActionBarContributor {
+<img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag"> protected void buildActions() {
+ this.addRetargetAction(new UndoRetargetAction());
+ this.addRetargetAction(new RedoRetargetAction());
+ this.addRetargetAction(new DeleteRetargetAction());
+ }
+
+ public void contributeToToolBar(IToolBarManager toolBarManager) {
+ super.contributeToToolBar(toolBarManager);
+ toolBarManager.add(getAction(ActionFactory.UNDO.getId()));
+ toolBarManager.add(getAction(ActionFactory.REDO.getId()));
+ }
+
+ protected void declareGlobalActionKeys() {
+<img src="images/tag_2.gif" height=13 width=24 align="middle" alt="tag"> this.addGlobalActionKey(ActionFactory.SELECT_ALL.getId());
+ }
+}</pre>
+ <div class="figure-caption">
+ <span class="figure-number">Fig 11</span>. Connecting menu actions
+ </div>
+</div>
+
+<p>
+ It may be illustrative to trace what happens when the user selects
+ the <em>Delete</em> item in the <em>Edit</em> menu (see Figure&nbsp;12). The
+ delete action, which is added to the action registry by the
+ parent class of the <code>ShapesEditor</code> class, traces the
+ current selection. When the delete action is executed, it checks
+ if any of the currently selected objects are instances of the
+ <code>EditPart</code> class. For each such object it requests a command
+ from the edit part. In turn, each edit part checks if any of the
+ edit policies created on it understand and are willing to handle
+ the delete request. For shapes, the <code>ShapeComponentEditPolicy</code>
+ claims it can handle the delete request, and when asked for a command
+ it returns a <code>ShapeDeleteCommand</code> instance. The
+ action executes the command, which removes the shape from
+ the diagram. The diagram fires a property change event that is
+ handled by the <code>DiagramEditPart</code> and ultimately leads to
+ a rectangle or ellipse representing the deleted shape to be removed from the
+ display.
+</p>
+<div class="figure">
+<center>
+ <img src="images/delete_action3.gif" alt="Delete action call sequence" width="575" height="340"/>
+</center>
+<div class="figure-caption">
+ <span class="figure-number">Fig 12</span>. Delete action call sequence
+</div>
+</div>
+
+<h3>Exposing properties</h3>
+
+<p>
+ Every graphical editor is a source of selection events. You can test this
+ by creating a view that registers with the workbench site's page as a selection listener.
+ Every time you select an object in your graphical editor, your view
+ receives a notification in the <code>selectionChanged</code> method. One
+ of Eclipse's standard views, <em>Properties</em> view, listens to
+ selection events, and for every selection checks if its objects implement
+ the <code>IPropertySource</code> interface. If so, it uses the methods of
+ the interface to interrogate the selected object or objects about their
+ properties and displays them in a tabular format.
+</p>
+
+<p>
+ Thanks to the above described infrastructure, exposing properties of objects
+ edited in graphical editor is a matter of implementing methods of the
+ <code>IPropertySource</code> interface. By inspecting the <code>Shape</code>
+ class you can view how position and size of objects are made
+ available to the <em>Properties</em> view.
+</p>
+
+<h3>Providing an Outline</h3>
+
+<p>
+ The <em>Outline</em> view is used to provide an alternative and often more
+ succinct view of edited data. In Java editors it is used to show
+ imports, variables, and methods of the edited class, without going into
+ code details. Graphical editors can also benefit from such a high level
+ view. The shape diagram editor, similarly to the logic circuit editor,
+ exposes the edited contents in the form of a tree (see
+ <a href="#fig1">Figure&nbsp;1</a>). The database schema editor
+ <a class="cite" href="#zoio">[7]</a> provides a view of the entire editor window
+ with a thumb for panning.
+</p>
+
+<p>
+ In order to expose edited content to the <em>Outline</em> view, you need to
+ override the <code>getAdapter</code> method and
+ <img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag">
+ return an outline
+ implementation when the adapter class is the <code>IContentOutlinePage</code>
+ interface. The easiest way to implement an outline is to extend
+ the <code>ContentOutlinePage</code> class by supplying it with an
+ appropriate configured <code>EditPartViewer</code>.
+</p>
+
+<div class="figure">
+ <pre class="program">public Object getAdapter(Class type) {
+ // returns the content outline page for this editor
+<img src="images/tag_1.gif" height=13 width=24 align="middle" alt="tag"> if (type == IContentOutlinePage.class) {
+ if (outlinePage == null) {
+ outlinePage = new ShapesEditorOutlinePage(this, new TreeViewer());
+ }
+ return outlinePage;
+ }
+ return super.getAdapter(type);
+}</pre>
+ <div class="figure-caption">
+ <span class="figure-number">Fig 13</span>. Providing an overview
+ </div>
+</div>
+
+<p>
+ In the case of the shape diagram editor, the edit part view is implemented by
+ a tree viewer. You should supply it with the same edit domain as your
+ main editor. A tree viewer, just like any other <code>EditPartViewer</code>,
+ requires a method for creating child edit parts. The editor uses the same
+ mechanism as that employed with the <code>DiagramEditPart</code>, by
+ setting an edit part factory on it. In addition, the selection of the
+ overview and the main editor window is synchronized using a
+ selection synchronizer, a GEF utility class that reconciles the selection
+ state of two edit parts. The <code>ShapesTreeEditPartFactory</code>
+ returns either a <code>ShapeTreeEditPart</code> or a
+ <code>DiagramTreeEditPart</code> instance, depending on the model type. By
+ inspecting those classes, the reader should have no difficulty recognizing
+ already familiar patterns. Both edit parts implement the
+ <code>PropertyChangeListener</code> interface and react to property changes
+ by adjusting visual representation of the model. Both install edit policies
+ to control types of interactions exposed through them.
+</p>
+
+<h2>Design patterns used by GEF</h2>
+
+<p>
+ GEF attains its flexibility through an extensive use of design patterns. Provided
+ here is a brief summary of those most commonly encountered. For a more
+ detailed treatment on patterns please see <a class="cite" href="#gamma">[2]</a>.
+<p>
+<dl>
+ <dt>Model-View-Controller</dt>
+ <dd>
+ The MVC pattern is used by GEF to decouple user interface, behavior,
+ and presentation. The model is represented by any Java <code>Object</code>.
+ The view must implement the <code>IFigure</code> interface. The controller
+ is a type of an <code>EditPart</code>.
+ </dd>
+ <dt>Command</dt>
+ <dd>
+ Commands encapsulate model changes, therefore providing support for undoable
+ operations.
+ </dd>
+ <dt>Chain of Responsibility</dt>
+ <dd>
+ Decouples senders of requests (tools) from receivers by giving more than
+ one object a chance to handle the request. In the case of GEF, multiple edit
+ policies may respond to a request with <code>Commands</code> which then
+ are chained together.
+ </dd>
+ <dt>State</dt>
+ <dd>
+ Allows editor to alter its behavior when its internal state changes. With
+ GEF editors, this change is implemented by switching tools. For
+ example, a marquee tool causes the editor to respond differently to a
+ mouse down event than when a create tool is active.
+ </dd>
+ <dt>Abstract Factory</dt>
+ <dd>
+ Provides an interface for creating families of related or dependent
+ objects. This pattern is used when creating edit parts controlling
+ given model parts.
+ </dd>
+ <dt>Factory Method</dt>
+ <dd>
+ Defines a method for creating an object, but lets subclasses decide
+ which class to instantiate. While not explicitly discussed, this is
+ an alternative method for creating an edit part. The method
+ <code>createChild</code> allows you to explicitly create child
+ edit parts without using a factory.
+ </dd>
+</dl>
+
+<h2>Summary</h2>
+
+<p>
+ I tried giving a detailed description of most aspects of a very simple
+ graphical editor. Hopefully there is enough information provided to allow
+ anybody patient enough to read this lengthy essay to inspect larger examples,
+ such as the logic circuit editor.
+ By immediately understanding roles of classes such as
+ <code>CircuitEditPart</code>, <code>AndGateFigure</code>, and a few others
+ that directly correspond to classes present in the simple shape editor,
+ you may focus your attention on more complex aspects of larger examples.
+ There exists a plethora of subjects and techniques in GEF whose surface I have not
+ even scratched. However, they should be studied only after the base is
+ well understood. After all, what is the purpose of trying to design
+ a drag feedback, if it takes you a few hours to enable the <em>Select All</em>
+ menu item?
+</p>
+
+<h2>Acknowledgments</h2>
+<p>
+ I would like to thank Randy Hudson for his comments that helped improve
+ the structure and accuracy of this article. My thanks also go to Jill
+ Sueoka for tirelessly reviewing numerous versions that I managed to
+ produce.
+</p>
+
+<h2>Bibliography</h2>
+
+<table>
+<tbody>
+ <tr>
+ <td valign="top"><a name="bordeau"></a>[1]</td>
+ <td> Eric Bordeau, <a href="../Article-GEF-dnd/GEF-dnd.html"><i>Using
+ Native Drag and Drop with GEF</i></a>, Eclipse Corner Article, August
+ 2003 </td>
+ </tr>
+ <tr>
+ <td valign="top"><a name="gamma"></a>[2]</td>
+ <td> Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, <i>Design
+ Patterns: Elements of Reusable Object-Oriented Software</i>, Addison Wesley,
+ 1995, ISBN 0-201-63361-2</td>
+ </tr>
+ <tr>
+ <td valign="top"><a name="hudson"></a>[3]</td>
+ <td> Randy Hudson, <a href="http://www-106.ibm.com/developerworks/opensource/library/os-gef/" target="_blank"><i>Create
+ an Eclipse-based application using the Graphical Editing Framework</i></a>,
+ <a href="http://www-136.ibm.com/developerworks/java/">IBM developerWorks</a>,
+ July 2003 </td>
+ </tr>
+ <tr>
+ <td valign="top"><a name="lee"></a>[4]</td>
+ <td> Daniel Lee, <a href="../Article-GEF-Draw2d/GEF-Draw2d.html"><i>Display
+ a UML Diagram using Draw2D Diagram</i></a>, Eclipse Corner Article, August
+ 2003 </td>
+ </tr>
+ <tr>
+ <td valign="top"><a name="mehaut"></a>[5]</td>
+ <td> Xavier Mehaut et al., <a href="http://eclipsewiki.editme.com/GefDescription" target="_blank"><i>Synthetic
+ GEF description</i></a>, June 2004 </td>
+ </tr>
+ <tr>
+ <td valign="top"><a name="moore"></a>[6]</td>
+ <td> William Moore, David Dean, Anna Gerber, Gunnar Wagenknecht and Philippe
+ Vanderheyden, <i><a href="http://www.redbooks.ibm.com/abstracts/sg246302.html" target="_blank">Eclipse
+ Development using the Graphical Editing Framework and the Eclipse Modeling
+ Framework</a></i>, IBM RedBooks, 2004, ISBN 0738453161</td>
+ </tr>
+ <tr>
+ <td valign="top"><a name="zoio"></a>[7]</td>
+ <td> Phil Zoio, <a href="../Article-GEF-editor/gef-schema-editor.html"><i>Building
+ a Database Schema Diagram Editor with GEF</i></a>, Eclipse Corner Article,
+ September 2004 </td>
+ </tr>
+</tbody>
+</table>
+
+<p><small>Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun
+Microsystems, Inc. in the United States, other countries, or both.</small></p>
+</body>
+
+</body>
+</html>
diff --git a/Article-GEF-dnd/DNDExample.java b/Article-GEF-dnd/DNDExample.java
new file mode 100644
index 0000000..ed41293
--- /dev/null
+++ b/Article-GEF-dnd/DNDExample.java
@@ -0,0 +1,57 @@
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.*;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.*;
+
+public class DNDExample {
+
+public static void main(String[] args) {
+ Shell shell = new Shell();
+ shell.setLayout(new FillLayout());
+
+ // Create the tree and some tree items
+ final Tree tree = new Tree(shell, SWT.NONE);
+ TreeItem item1 = new TreeItem(tree, SWT.NONE);
+ item1.setText("Item 1");
+ TreeItem item2 = new TreeItem(tree, SWT.NONE);
+ item2.setText("Item 2");
+ TreeItem item3 = new TreeItem(tree, SWT.NONE);
+ item3.setText("Item 3");
+ TreeItem item4 = new TreeItem(tree, SWT.NONE);
+ item4.setText("Item 4");
+
+ // Create the drag source on the tree
+ DragSource ds = new DragSource(tree, DND.DROP_MOVE);
+ ds.setTransfer(new Transfer[] {TextTransfer.getInstance()});
+ ds.addDragListener(new DragSourceAdapter() {
+ public void dragSetData(DragSourceEvent event) {
+ // Set the data to be the first selected item's text
+ event.data = tree.getSelection()[0].getText();
+ }
+ });
+
+ // Create the button
+ final Button button = new Button(shell, SWT.FLAT);
+ button.setText("Button");
+ button.setAlignment(SWT.CENTER);
+
+ // Create the drop target on the button
+ DropTarget dt = new DropTarget(button, DND.DROP_MOVE);
+ dt.setTransfer(new Transfer[] {TextTransfer.getInstance()});
+ dt.addDropListener(new DropTargetAdapter() {
+ public void drop(DropTargetEvent event) {
+ // Set the buttons text to be the text being dropped
+ button.setText((String)event.data);
+ }
+ });
+
+ shell.pack();
+ shell.open();
+ Display display = Display.getDefault();
+ while (!shell.isDisposed())
+ if (!display.readAndDispatch())
+ display.sleep();
+ display.dispose();
+}
+
+}
diff --git a/Article-GEF-dnd/GEF-dnd.html b/Article-GEF-dnd/GEF-dnd.html
new file mode 100644
index 0000000..8fbe48e
--- /dev/null
+++ b/Article-GEF-dnd/GEF-dnd.html
@@ -0,0 +1,321 @@
+<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name="Author" content="Eric Bordeau">
+<link rel="stylesheet" href="../default_style.css">
+<title>Using Native Drag and Drop with GEF</title>
+</head>
+
+<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
+
+<div align="right">
+ <font face="Times New Roman, Times, serif"><font size="-1">Copyright © 2003 International Business
+ Machines Corp.</font></font></div>
+<table border="0" cellspacing="0" cellpadding="2" width="100%">
+ <tr>
+ <td align="left" valign="top" colspan="2" bgcolor="#0080c0"><b><font face="Arial,Helvetica"
+ color="#ffffff">Eclipse Corner Article</font></b></td>
+ </tr>
+</table>
+<div align="left">
+ <h1><img src="../images/Idea.jpg" height="86" width="120" align="middle"></h1>
+</div>
+<p>&nbsp;</p>
+<h1 align="center">Using Native Drag and Drop with GEF</h1>
+<blockquote>
+ <b>Summary</b> <br>
+ Native drag and drop provides the ability to drag data from one GUI object to another GUI
+ object, which could potentially be in another application. GEF allows access to the operating
+ system's underlying drag and drop infrastructure through SWT. This article will provide an in-depth look at GEF&#39;s drag and drop functionality and show some simple
+ examples of how to take advantage of this API.<p><b>Eric Bordeau, IBM</b> <br>
+ August 25, 2003</p>
+</blockquote>
+<hr width="100%">
+<h2>Introduction</h2>
+<p>Native drag and drop means the operating system&#39;s underlying drag and drop mechanism is used. This is
+different from when you drag EditParts around inside a single viewer. By using native drag and drop,
+you can transfer items between views, editors, windows and even between different applications (providing
+both applications support the transfer of that particular type of object). But not only will you be able to
+utilize other plug-ins&#39; and applications&#39; drag and drop capabilities, the opposite is also true. By using
+native drag and drop, you open the door for other plug-ins and applications to interact with your application
+in ways you may not have envisioned.
+</p>
+<h2>An SWT Example</h2>
+<p>In order to access the operating system&#39;s drag and drop facilities, GEF
+ uses SWT&#39;s DragSource and DropTarget API. (If you would like more information
+ on how SWT's drag and drop mechanism works, see Veronika Irvine's <a href="../Article-SWT-DND/DND-in-SWT.html">SWT
+ drag and drop article</a>.) To use SWT's drag and drop support, you need to
+ create a DragSource and/or DropTarget for your control. Then you can add DragSourceListeners
+ and/or DropTargetListeners to handle the drag and drop events. Here's a simple
+ drag and drop example that allows you to drag from a tree and drop the tree
+ item into a text field, changing the text field's text to that of the tree item.
+</p>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td>
+ <pre>import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.*;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+
+public class DNDExample {
+
+ public static void main(String[] args) {
+ Shell shell = new Shell();
+ shell.setBackground(new Color(null, 200, 200, 200));
+ shell.setLayout(new GridLayout(2, false));
+
+ // Create the tree and some tree items
+ final Tree tree = new Tree(shell, SWT.NONE);
+ TreeItem item1 = new TreeItem(tree, SWT.NONE);
+ item1.setText(&quot;Item 1&quot;);
+ TreeItem item2 = new TreeItem(tree, SWT.NONE);
+ item2.setText(&quot;Item 2&quot;);
+
+ // Create the drag source on the tree
+ DragSource ds = new DragSource(tree, DND.DROP_MOVE);
+ ds.setTransfer(new Transfer[] {TextTransfer.getInstance()});
+ ds.addDragListener(new DragSourceAdapter() {
+ public void dragSetData(DragSourceEvent event) {
+ // Set the data to be the first selected item's text
+ event.data = tree.getSelection()[0].getText();
+ }
+ });
+
+ // Create the text field
+ final Text text = new Text(shell, SWT.NONE);
+
+ // Create the drop target on the text field
+ DropTarget dt = new DropTarget(text, DND.DROP_MOVE);
+ dt.setTransfer(new Transfer[] {TextTransfer.getInstance()});
+ dt.addDropListener(new DropTargetAdapter() {
+ public void drop(DropTargetEvent event) {
+ // Set the text field's text to the text being dropped
+ text.setText((String)event.data);
+ }
+ });
+
+ shell.pack();
+ shell.open();
+ Display display = Display.getDefault();
+ while (!shell.isDisposed())
+ if (!display.readAndDispatch())
+ display.sleep();
+ display.dispose();
+ }
+}</pre></td></tr></table>
+<p>The DragSourceListener needs to set the data being dragged during
+the dragSetData event and the DropTargetListener needs to do something with that data during the
+drop event.<p>GEF uses SWT's DragSource and DropTarget to facilitate its drag and drop function. When adding a drag listener to your EditPartViewer, a DragSource gets created and hooked into the
+underlying control. And similarly, a DropTarget gets created when adding a drop listener. But instead
+of adding your listener directly to the DragSource or DropTarget, the viewer creates a DelegatingDragSourceAdapter
+or DelegatingDropTargetAdapter, respectively, and adds them to their corresponding widget. Then, your
+listener gets added to the delegating adapter. When events are dispatched by the DragSource or DropTarget,
+the corresponding delegating adapter gets notified and it in turn delegates the event to the proper
+listener.</p>
+<p>One of the advantages of delegating the drag and drop events in this way is to ease the separation
+of listeners by Transfer type. Code is simpler to read because each listener is only concerned with
+one type of transfer. And extension of drag and drop functionality is simplified since all
+that needs to be done is to add a new listener. Delegation of drag and drop events allows for a
+consensus of all the available listeners -- if one listener can handle the drag, it's allowed to do
+so, instead of letting the last listener determine whether the drag will be aborted or not. SWT lets you add
+multiple listeners but doesn't achieve the same effect. Delegating allows for easier
+maintainability of code and extension by third-party plug-ins.</p>
+<h2>Adding a Listener to a Graphical Editor</h2>
+<p>Let&#39;s just get started with some code. I'll be describing how to add drop functionality to the logic editor
+(available from our <a href="http://download.eclipse.org/tools/gef/downloads/">download page</a>).
+This will
+allow the user to drag files from the Navigator or Package Explorer (or any file explorer that
+supports dragging files) and drop them onto the logic editor.
+The editor will respond by creating a new label with the file name as its text. First off, you need
+a TransferDropTargetListener (GEF provides you with AbstractTransferDropTargetListener for you to subclass).
+Create a subclass called FileTransferDropTargetListener:
+</p>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>package org.eclipse.gef.examples.logicdesigner.dnd;
+
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.dnd.AbstractTransferDropTargetListener;
+
+public class FileTransferDropTargetListener
+ extends AbstractTransferDropTargetListener
+{
+
+ public FileTransferDropTargetListener(EditPartViewer viewer, Transfer xfer) {
+ super(viewer, xfer);
+ }
+
+ public FileTransferDropTargetListener(EditPartViewer viewer) {
+ super(viewer, FileTransfer.getInstance());
+ }
+
+ protected void updateTargetRequest() {}
+
+}</pre></td>
+ </tr>
+</table>
+<p>The first thing you need to do is override createTargetRequest() to create the appropriate request.
+CreateRequest should be used so that a new label will be created when a file is dropped on the editor.
+The CreateRequest needs a CreationFactory to create the new object that will be passed to the command.
+You should implement your own factory that will create a new LogicLabel based on the file name (which you will
+set later during the drop event).</p>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>package org.eclipse.gef.examples.logicdesigner.dnd;
+
+import org.eclipse.gef.requests.CreationFactory;
+import org.eclipse.gef.examples.logicdesigner.model.LogicLabel;
+
+public class FileLabelFactory implements CreationFactory {
+
+ private String text = &quot;&quot;;
+
+ public Object getNewObject() {
+ LogicLabel label = new LogicLabel();
+ label.setLabelContents(text);
+ return label;
+ }
+
+ public Object getObjectType() {
+ return LogicLabel.class;
+ }
+
+ public void setText(String s) {
+ text = s;
+ }
+}</pre></td></tr></table>
+<p>Now that we&#39;ve got our factory, we can add a field to our drop listener to store this factory...</p>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>private FileLabelFactory factory = new FileLabelFactory();</pre></td>
+ </tr>
+</table>
+<p>and set the factory on the CreateRequest during createTargetRequest()...</p>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>protected Request createTargetRequest() {
+ CreateRequest request = new CreateRequest();
+ request.setFactory(factory);
+ return request;
+}</pre></td>
+ </tr>
+</table>
+<p>Next, implement updateTargetRequest() by setting the current drop location on the request.</p>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>protected void updateTargetRequest() {
+ ((CreateRequest)getTargetRequest()).setLocation(getDropLocation());
+}</pre></td>
+ </tr>
+</table>
+<p>
+Now since we&#39;ll be dragging files from the Navigator (or any file explorer), we want to ensure that
+the file won&#39;t be deleted. To do this, override handleDragOver() and set the drop detail to DND.DROP_COPY.
+If we leave it as the default (DND.DROP_MOVE), after the drop the drag source will assume the file
+is somewhere else and remove the original. We want the file to stay right where it is.</p>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>protected void handleDragOver() {
+ getCurrentEvent().detail = DND.DROP_COPY;
+ super.handleDragOver();
+}</pre></td>
+ </tr>
+</table>
+<p>Finally, we need to implement handleDrop() to get the file name from
+the current DropTargetEvent. The data field of the event is typed as Object but
+the actual data type is dependent on the transfer type. For FileTransfers, the
+data is a String array storing the full paths of the files being dragged. To make
+this easier, we&#39;ll only be concerned with the first file in the list and we&#39;ll
+only display the file name, not the full path. Once we extract this information
+from the current event, set the text on the factory and the superclass will do
+the rest.</p>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>protected void handleDrop() {
+ String s = ((String[])getCurrentEvent().data)[0];
+ String separator = System.getProperty("file.separator");
+ s = s.substring(s.lastIndexOf(separator) + 1);
+ factory.setText(s);
+ super.handleDrop();
+}</pre></td>
+ </tr>
+</table>
+<p>
+That&#39;s all we need to do to implement our drop listener. The superclass will take care obtaining a Command from the target edit part and executing it. All that&#39;s left
+is to add the listener to our editor and see what happens. To do this, we need to change initializeGraphicalViewer()
+in the LogicEditor class. Notice there are already 2 drop listeners being added -- a LogicTemplateTransferDropTargetListener,
+which allows for dragging templates from the palette and dropping them onto the editor for creation;
+and a TextTransferDropTargetListener, which allows the user to drag text (such as from a word
+processor) and drop it on an already existing label
+to change the label text to match the text being dragged. We need to add our listener to the viewer by
+adding the following line to this method:</p>
+<table border cols="1" width="100%" bgcolor="#CCCCCC">
+ <tr>
+ <td><pre>getGraphicalViewer().addDropTargetListener(
+ new FileTransferDropTargetListener(getGraphicalViewer()));</pre></td>
+ </tr>
+</table>
+<h2>Behind The Scenes</h2>
+<p>For most people, all you need (or want) to know is that when you add a listener to a viewer, the
+viewer creates a new DragSource or DropTarget, if one has not already been created. The viewer
+also ensures the DragSource/DropTarget is aware of the Transfers from all of the listeners that have
+been added. For those of you interested in a more intricate look at what's happening behind
+the scenes, read on. (I'll be explaining how drop
+listeners are added, but drag listeners work in a similar fashion.)
+</p>
+<p>When you add a TransferDropTargetListener to an EditPartViewer, the viewer adds the listener to the
+DelegatingDropAdapter. Next, the DropTarget is refreshed. During the refresh, the viewer
+checks to see if the DelegatingDropAdapter is empty (i.e. it has no listeners) and if so, sets the
+DropTarget (an SWT widget) to null. This occurs because when there are no listeners to delegate the drop
+events to, there's no reason to be notified of these drop events. When the first listener is
+added to the DelegatingDropAdapter (in other words, the DelegatingDropAdapter is not empty but the
+DropTarget is still null), the viewer creates a new DropTarget for the viewer's control and sets all
+possible styles (DND.DROP_MOVE, DND.DROP_COPY, DND.DROP_LINK). This makes all styles available to
+the delegated listeners, even if they don't use them. Finally, the viewer sets the Transfer types on
+the DropTarget by getting them from the DelegatingDropAdapter. The DelegatingDropAdapter
+obtains these transfer types by querying all of its listeners for their transfer types and adding
+them all to an array. This completes the DropTarget setup and the DelegatingDropAdapter will now be
+notified of DropTargetEvents. WARNING: You can't mix your own DropTarget with the DropTarget created
+by the viewer. This is because, according to the DropTarget javadoc, &quot;there can only be a one
+to one mapping between a Control and a DropTarget.&quot; If you try to create another DropTarget on the
+same control, you'll get an error.</p>
+<p>The DelegatingDropAdapter chooses one listener to be active
+(inactive listeners will not receive events) and refreshes the active listener before each event. To
+be considered active, a listener must satisfy three conditions: 1) The transfer type of the listener
+must match up with the transfer type
+of the data being dragged. 2) There must be an EditPart under the mouse cursor that understands the
+listeners request. 3) The listener must be the first listener in the list to satisfy the first two
+conditions. The active listener could potentially change during each event, based on mouse location,
+modifier keys pressed, etc. In AbstractTransferDropTargetListener.isEnabled(DropTargetEvent), the
+listener tries to match its transfer type with one of the supported transfer types in the event. If
+a match is found, the listener tries to find an EditPart at the current mouse location that
+understands its target request. If a target edit part is found, the listener is enabled and
+the DelegatingDropTargetAdapter stops looking for listeners to handle this event. Then the event is
+actually delegated to the active listener. If the active listener changes, the old listener gets a
+dragLeave() event and the new listener gets a dragEnter() event to ensure proper initialization and
+clean-up is available.</p>
+<h2>Summary</h2>
+<p>Adding drag and drop support to an EditPartViewer is a fairly simple task. And by doing so, your GEF
+application will be able to interact with other views, editors and applications by transferring data
+at the OS level. All that is really needed is a subclass of AbstractTransferDragSourceListener or
+AbstractTransferDropTargetListener added to the viewer with the appropriate Transfer type. In
+this article, I introduced a very simple drop listener to demonstrate how easy it is to implement
+such a feature. Real-world applications would most likely perform a more meaningful task, but
+the overall process is the same.</p>
+<h2>Source Code</h2>
+<p>You can get the source code for the standalone SWT example <a href="DNDExample.java">here</a>.</p>
+<h2>Acknowledgements</h2>
+<p>The author would like to thank Randy Hudson, Daniel Lee, David Williams, and
+ Nitin Dahyabhai for providing constructive comments on the article.</p>
+<p><small>Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun
+Microsystems, Inc. in the United States, other countries, or both.</small></p>
+
+</body>
+
+</html>
diff --git a/Article-GEF-editor/gef-schema-editor.html b/Article-GEF-editor/gef-schema-editor.html
new file mode 100644
index 0000000..75a83e9
--- /dev/null
+++ b/Article-GEF-editor/gef-schema-editor.html
@@ -0,0 +1,1000 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
+<title>Building a Database Schema Diagram Editor with GEF</title>
+<link rel="stylesheet" href="../default_style.css"/>
+</head>
+
+<BODY vLink=#800080 link=#0000FF>
+<DIV align=right>&nbsp; <FONT face="Times New Roman, Times, serif"><FONT
+ size=-1>Copyright © 2004 Realsolve Solutions Ltd.</FONT></FONT></DIV>
+&nbsp;
+<DIV align=right>
+ <table cellspacing=0 cellpadding=2 width="100%" border=0>
+ <tbody>
+ <tr>
+ <td valign=top align=left bgcolor=#0080c0 colspan=2><b><font
+ face=Arial,Helvetica><font color=#ffffff>&nbsp;Eclipse Corner
+ Article</font></font></b></td>
+ </tr>
+ </tbody>
+ </table>
+</DIV>
+<H1><IMG border="0" src="images/Idea.jpg" width="120" height="86"></H1>
+<CENTER>
+ <h1>Building a Database Schema Diagram Editor<br>
+ with GEF</h1>
+</CENTER>
+
+<blockquote>
+<b>Summary</b>
+
+<br>
+ GEF is a very powerful framework for visually creating and editing models. With a small initial investment,
+ even the relative Eclipse novice can be quickly up and running, building applications with graphical editing capabilities.
+ To illustrate, this article uses a relational database schema diagram editor with a deliberately
+ simplified underlying model, but with enough bells and whistles to show some of the interesting features of GEF at work.
+ <p><b> Phil Zoio, Realsolve Solutions Ltd.</b> <br>
+ <font size="-1">September 27, 2004</font> </p>
+</blockquote>
+
+<hr width="100%">
+
+<h2>Introduction</h2>
+<p>
+Having graphical editing capabilities can be a real asset, if not an essential feature, for many tools and applications. Examples are not
+hard to think of: UML tools, GUI builders, in fact, any application which comprises a dynamic model which can be visualized.
+With GEF, Eclipse developers have at their disposal a framework which can really simplify development of graphical editors.
+This article uses a simple but non-trivial example to show how a GEF application works -
+and what you need to do to get it to perform its little miracles.
+</p>
+<p>
+The screenshot below shows what our example editor looks like.
+The edit area uses a "flyout" palette which contains some very basic entries and can be minimized to increase the editable screen area.
+On the right side is a scrollable graphical viewer containing the tables and their relationships.
+</p>
+<p> <img src="images/editor.JPG" height=645 width=597 align=CENTER></p>
+
+<p> <img src="images/tryit.gif" width="61" height="13"> Download and unzip the
+ example plug-in <a href="schemaeditor.zip">schemaeditor.zip</a> into your <i>eclipse/</i>
+ directory, then create a new diagram by launching the wizard from the File menu:
+ File -> New -> Example ... -> GEF (Graphical Editing Framework) -> Schema Diagram
+ Editor. </p>
+
+<p>
+At the heart of GEF is the <B>Model-View-Controller</B> pattern, discussed in Randy Hudson's introductory tutorial
+<i><a href="http://www-106.ibm.com/developerworks/opensource/library/os-gef/" target="_blank">How to Get Started with the GEF</a></i>, and also
+providing a focus for much of this article.
+</p>
+<h2>The Model</h2>
+<p>
+The starting point for any GEF application is the model. This is what needs to be displayed, edited and persisted.
+Our somewhat oversimplified model contains the following classes:
+</p>
+<ul>
+ <li><CODE>Table</CODE>: represents a relational database table. The only attribute that the table holds itself is the name</li>
+ <li><CODE>Column</CODE>: represents a table column. Here we are interested in the column name and the type of data, which itself can either be <CODE>VARCHAR</CODE> or <CODE>INTEGER</CODE></li>
+ <li><CODE>Relationship</CODE>: represents a primary key/foreign key relationship between two tables.
+ The foreign key table we denote the <B>source</B> of the relationship, while the primary key table is the <B>target</B>.
+ Note that our model applies a relationship directly between two tables,
+ rather than between foreign and primary key fields in the respective tables,
+ as we would in the real world</li>
+ <li><CODE>Schema</CODE>: simply represents all the tables we plan to group together (and ultimately show on the same diagram)</li>
+</ul>
+Our model is extremely simple, but does at least include the two key forms of relationship in a typical GEF model:
+<ul>
+ <li>The <B>parent-child</B> relationship that exists between schemas and tables, and between tables and columns</li>
+ <li><B>Connections</B> between different <B>nodes</B>.
+ In our example application, the connections are in the form of primary key/foreign key relationships, with the nodes being the tables</li>
+</ul>
+<p>
+Of course, we need to decide what we want our editor to be able to do with the model. Here, we want to be able to:
+</p>
+<ul>
+ <li>lay our tables nicely on the diagram. The diagram must scale to accommodate any growth in our model, and should be readable</li>
+ <li>add new tables to our schema, and new columns to our table, using either drag and drop or point and click</li>
+ <li>directly edit the names of the tables as well as both the names and types of our columns. In both cases, we want validation to tell us when we are typing in nonsense</li>
+ <li>use drag and drop to set up relationships between tables, as well as to change these relationships</li>
+ <li>use drag and drop to move column definitions from one table to another, or to reorder columns within tables</li>
+ <li>be able to delete tables, columns and relationships by hitting the delete key</li>
+ <li>have a choice between manually laying out our diagram, and having this done automatically. When using manual layout, we want to be able to
+ shift our tables around using drag and drop</li>
+</ul>
+There are of course many more things we would like to be able to do with our editor,
+but we have enough here to be able to test out many of the most commonly used GEF features.
+<h2>The View</h2>
+
+<h3>Figures</h3>
+<p>
+The display component in both GEF and draw2d is built around the draw2d <code>IFigure</code> interface.
+Figures in draw2d are lightweight objects which can be nested to create a complex graphical representation.
+The view is created by rendering and laying out the set of figures which reflect the model.
+In a typical GEF application, you would normally create a set of customized <code>IFigure</code> implementations, each subclassing <code>Figure</code>.
+</p>
+
+<p>
+<img src="images/tip.gif" width="62" height="13">
+If you're unfamiliar with draw2d and <code>Figures</CODE>, take a look at Daniel Lee's article on <i><a href="../Article-GEF-Draw2d/GEF-Draw2d.html">Display a UML Diagram using Draw2D</a></i>,
+</p>
+
+<p>
+In our application we have the following figures:
+<ul>
+ <li><CODE>EditableLabel</CODE>: a subclass of the draw2d <CODE>Label</CODE> class which itself
+ subclasses <CODE>Figure</CODE>. We need this for the column and table names</li>
+ <li><CODE>ColumnsFigure</CODE>: a container for all the column labels</li>
+ <li><CODE>TableFigure</CODE>: contains an <CODE>EditableLabel</CODE> for the table name, as well as a <CODE>ColumnsFigure</CODE> for the column names</li>
+ <li><CODE>SchemaFigure</CODE>: a container for all the <CODE>TableFigures</CODE> in the schema</li>
+</ul>
+<p>
+We haven't provided any custom figures to represent connections - we simply use the draw2d <CODE>PolylineConnection</CODE> class,
+which is a just a line with zero or more kinks or bend points.
+</p>
+<p>
+Because the table names as well as the number of columns and their names are likely to change during the lifetime of a <CODE>TableFigure</CODE> instance,
+we want our <CODE>ColumnsFigure</CODE> and <CODE>TableFigure</CODE> to be resizable.
+A key role in allowing this to happen is played by layout managers, another important part of the draw2d framework.
+</p>
+
+<h3>Layout Management</h3>
+<p>
+GEF provides a layout management framework which is distinct from the Swing and Eclipse SWT layout managers:
+its job is specifically to handle layout of the child figures of draw2d <CODE>IFigure</CODE> instances.
+Your job as an application developer is to decide which layout manager to use
+for each figure containing child figures.</p>
+<p>
+Broadly speaking, there are three types of layout managers:
+<ul>
+ <li><B>Structured layout managers</B>, such as <CODE>FlowLayout</CODE> and <CODE>ToolbarLayout</CODE>,
+ which lay out child figures according to their <B>order</B> by arranging them vertically or horizontally
+ <li><B>Constraint-based layout managers</B>, such as the <CODE>XYLayout</CODE> and the <CODE>DelegatingLayout</CODE>.
+ Here the application itself participates directly in the placement of figures by setting a constraint <CODE>Object</CODE>
+ for each child figure. In the case of the <CODE>XYLayout</CODE>, this object is a <CODE>Rectangle</CODE>
+ with specified location and size</li>
+ <li>
+ <B>Layout using geometry computation algorithms</B>. Here layout is determined by applying a series of rather complex algorithms to
+ calculate the "best" layout for child figures. The algorithms take a specially constructed data structure as input and
+ deliver as their output a solution to geometrical problems such as node placement and routing of paths.
+ The algorithms provided by GEF are in the classes <CODE>DirectedGraphLayout</CODE>
+ and <CODE>CompoundDirectedGraphLayout</CODE>
+ </li>
+</ul>
+<p>
+The GEF developer needs to understand which layout managers can be best applied in which situation.
+Structured layout managers are suitable when there is a well defined parent-child relationship between the
+containing figure and its children <I>and</I>
+the children are not related to each other in arbitrary ways.
+In our example application, <CODE>TableFigure</CODE> uses a <CODE>ToolbarLayout</CODE> to place its children
+(simply stacking them vertically). The <CODE>ColumnsFigure</CODE> does the same with its child <CODE>Label</CODE> objects,
+but uses the <CODE>FlowLayout</CODE> for this purpose.
+<p>
+This kind of arrangement of course does not work with <CODE>SchemaFigure</CODE> -
+any of its child <CODE>TableFigures</CODE> may be related to any other via a primary key/foreign key relationship,
+so we cannot simply stack the table figures next to each other or side by side.
+For <CODE>SchemaFigure</CODE> we need to choose between either a constraint-based layout manager or a graph layout manager.
+In our example application we use both. Users can switch between manual layout, which involves dragging table figures
+to their desired locations, and automatic placement of figures using geometry computation algorithms.
+How this is done is beyond the scope of this article,
+although interested readers can examine the
+<CODE>DelegatingLayoutManager</CODE> class in the example application source code.
+
+<p>
+<img src="images/tryit.gif" width="61" height="13"> Open a schema diagram editor and make some changes, switching between manual
+and automatic layout using the
+<img src="images/layout.gif" width="16" height="16"> icon.
+</p>
+
+<h2>The Controller</h2>
+<p>
+We only really move into GEF territory proper when we start talking about the controller in the MVC trilogy.
+GEF provides an abstraction that prevents the model from having to know about the figures, and vice versa.
+At the centre of this architecture is the <CODE>EditPart</CODE> interface.
+</p>
+<h3>EditParts</h3>
+<p>
+The first thing to know is that typically every separately editable part of the model will need to be
+associated with an <CODE>EditPart</CODE> instance. This means that there will usually be a close to one-for-one mapping between classes
+in the model hierarchy and classes in the <CODE>EditPart</CODE> hierarchy.
+In most cases, an <CODE>EditPart</CODE> is also a <CODE>GraphicalEditPart</CODE>, which means that
+as well as managing a model component, it also has an associated view component. Because the
+model and view are completely decoupled, all coordination between the model and the view must be managed by the <CODE>EditPart</CODE>.
+This coordination can be divided into two separate areas of activity:
+<ol>
+ <li>Acting as a listener to changes in the model so that these can be propagated to the view, by calling layout related methods. We discuss this
+ in detail in the section <A HREF="#viewUpdate">Updating an Repainting the Display</A>
+ </li>
+ <li>Providing a means by which user interaction can be interpreted and propagated to changes in the model.
+ Central to this are <CODE>EditPolicies</CODE>, discussed in the section <A HREF="#editPolicies">EditPolicies and Roles</A>
+ </li>
+ <li>Managing what are known as direct edits, where the user types text directly into an editable control
+ </li>
+</ol>
+In our example application we have the following <CODE>EditPart</CODE> implementations
+<ul>
+ <li><CODE>SchemaDiagramPart</CODE>: represents a <CODE>Schema</CODE> instance and associated <CODE>SchemaFigure</CODE></li>
+ <li><CODE>TablePart</CODE>: represents a <CODE>Table</CODE> and manages the <CODE>TableFigure</CODE> and child view components</li>
+ <li><CODE>ColumnPart</CODE>: enables editing functionality for the column label</li>
+ <li><CODE>RelationshipPart</CODE>: represents a primary key/foreign key relationship.
+ In the same way that Relationship in the model is associated with two <CODE>Table</CODE> instances,
+ a <CODE>RelationshipPart</CODE> is associated with two <CODE>TableParts</CODE></li>
+</ul>
+<p>
+When an instance of any of these classes is created, it is automatically associated with a part of the model.
+This is a build-in feature of the framework. As part of our editor, we have to provide an <CODE>EditPartFactory</CODE> implementation.
+Ours looks like this:
+</p>
+<font color="#0000cc">
+<pre>public class SchemaEditPartFactory implements EditPartFactory
+{
+ public EditPart createEditPart(EditPart context, Object model)
+ {
+ EditPart part = null;
+ if (model instanceof Schema)
+ part = new SchemaDiagramPart();
+ else if (model instanceof Table)
+ part = new TablePart();
+ else if (model instanceof Relationship)
+ part = new RelationshipPart();
+ else if (model instanceof Column)
+ part = new ColumnPart();
+ part.setModel(model);
+ return part;
+ }
+}</pre>
+</font>
+<p>
+<CODE>SchemaDiagramPart</CODE>, <CODE>TablePart</CODE> and <CODE>ColumnPart</CODE>
+all extend <CODE>AbstractGraphicalEditPart</CODE> and implement <CODE>GraphicalEditPart</CODE>.
+In addition, <CODE>TablePart</CODE> can be a <I>node</I> in a primary/foreign key relationship,
+so it has to implement <CODE>NodeEditPart</CODE>.
+Finally, <CODE>RelationshipPart</CODE> represents the <I>connection</I> part of the relationship,
+so it extends <CODE>AbstractConnectionEditPart</CODE>.
+</p>
+<p>
+<CODE>SchemaDiagramPart</CODE>'s job is primarily managing the layout of the tables.
+<CODE>ColumnPart</CODE>'s role is relatively limited - it just needs to handle editing of the label displaying name and type information.
+</p>
+<p>
+Of the four of these, <CODE>TablePart</CODE> has the most to do.
+In GEF, most of the work that is done to manage relationships is done
+by <CODE>NodeEditPart</CODE>, and not <CODE>ConnectionEditPart</CODE>.
+Because we sometimes need to rename tables, <CODE>TablePart</CODE> also has to manage
+editing of the label that displays its name.
+We will spend more of our time focusing on <CODE>TablePart</CODE>.
+</p>
+
+
+In a GEF application, there are a number of tasks <CODE>EditPart</CODE> subclasses must
+fulfill:
+<ol>
+ <li>
+ <p>
+ Provide a figure instance to be associated with the <CODE>EditPart</CODE>.
+ In the case of <CODE>TablePart</CODE>, we simply return a new <CODE>TableFigure</CODE> instance with a name label:
+<font color="#0000cc">
+<pre> protected IFigure createFigure()
+ {
+ Table table = getTable();
+ EditableLabel label = new EditableLabel(table.getName());
+ TableFigure tableFigure = new TableFigure(label);
+ return tableFigure;
+ }</pre>
+ </font>
+ </li>
+ <li>
+ <p>
+ <CODE>EditParts</CODE> which represent parent objects in <B>parent-child</B> relationships need to override <CODE>getModelChildren()</CODE>.
+ In the case of <CODE>TablePart</CODE>, our
+ implementation of this method simply returns the <CODE>Column</CODE> objects it contains:
+<font color="#0000cc">
+<pre> protected List getModelChildren()
+ {
+ return getTable().getColumns();
+ }</pre>
+</font>
+ Note that the <CODE>AbstractEditPart</CODE> implements a parallel method <CODE>getChildren()</CODE>,
+ which returns the <CODE>EditPart</CODE> collection representing the model children.
+ In the case of <CODE>TablePart</CODE>, <CODE>getChildren()</CODE> returns a list of <CODE>ColumnPart</CODE> objects.
+ We know this because our implementation of <CODE>EditPartFactory</CODE> associates
+ <CODE>Column</CODE> model instances with instances of <CODE>ColumnPart</CODE>.
+ The <CODE>EditPart</CODE> <CODE>List</CODE> returned by <CODE>getChildren()</CODE>
+ always needs to be kept in sync with the <CODE>getModelChildren()</CODE>.
+ In the Section <A HREF="#synchronising">Synchronizing EditPart Relationships with Model Changes</A> we describe how this happens
+ <br>
+ </li>
+ <li>
+ <p>
+ If the parent <CODE>EditPart</CODE>'s figure is not the direct parent of the child <CODE>EditPart</CODE>'s figure, you will
+ need to override <CODE>AbstractGraphicalEditPart.getContentPane()</CODE>.
+ The <B>content pane</B> is the containing figure into which GEF adds figures created by child <CODE>EditParts</CODE>,
+ which is by default the figure returned by the <CODE>EditPart</CODE>'s <CODE>createFigure()</CODE> method.
+ </p>
+ <p>
+ In our example application
+ the column labels are not contained within a <CODE>TableFigure</CODE> but within its <CODE>ColumnsFigure</CODE> child.
+ Our implementation of <CODE>getContentPane()</CODE> in <CODE>TablePart</CODE> reflects this:
+<pre>public IFigure getContentPane()
+{
+ TableFigure figure = (TableFigure) getFigure();
+ return figure.getColumnsFigure();
+}</pre>
+<p>
+<img src="images/tip.gif" width="62" height="13"> Do not add and remove child figures
+by overriding <CODE>AbstractGraphicalEditPart.addChildVisual()</CODE> and <CODE>AbstractGraphicalEditPart.removeChildVisual()</CODE>.
+Override <CODE>getContentPane()</CODE> instead.
+</p>
+ </li>
+ <li>
+ <CODE>EditParts</CODE> which represent nodes (model objects which may participate in connections)
+ must also implement a number of additional methods defined in the interface <CODE>NodeEditPart</CODE>
+ <ul>
+ <li>
+ <p>
+ <CODE>protected List getModelSourceConnections()</CODE>: this returns all the connection model objects for which the
+ node model object is the source.
+ In our example application, we have identified foreign keys as the source of a primary key/foreign key relationship.
+ <CODE>TablePart</CODE>'s implementation contains just a single line of code:
+ </p>
+ <p>
+ <font color="#0000cc"><CODE>return getTable().getForeignKeyRelationships();</CODE></font>
+ </p>
+ <p>
+ This method simply returns the <CODE>Relationship</CODE> objects for
+ which the current <CODE>TablePart</CODE>'s <CODE>Table</CODE> is the foreign key.
+ Once again, there is a parallel method <CODE>getSourceConnections()</CODE>,
+ which returns the <CODE>List</CODE> of <CODE>RelationshipParts</CODE> associated with these relationships.
+ We also consider in the Section <A HREF="#synchronising">Synchronizing EditPart Relationships with Model Changes</A>
+ how the <CODE>ConnectionEditPart</CODE> list returned by
+ <CODE>getSourceConnections()</CODE> stays in sync with the
+ <CODE>Relationship</CODE> list returned by <CODE>getModelSourceConnections()</CODE>
+ </p>
+ </li>
+ <li>
+ <p>
+ <CODE>protected List getModelTargetConnections()</CODE>:
+ this works identically to <CODE>getModelSourceConnections()</CODE>,
+ except that it returns the <CODE>Relationship</CODE> objects for which the current
+ <CODE>TablePart</CODE>'s <CODE>Table</CODE> is the primary key
+ </p>
+ </li>
+ <li>
+ <p>
+ the node <CODE>GraphicalEditPart</CODE> must also provide implementations of the
+ <CODE>NodeEditPart</CODE> <CODE>getSourceConnectionAnchor()</CODE> and <CODE>getTargetConnectionAnchor()</CODE> methods.
+ In each case, these methods return objects which represent the points to which connections between nodes can be attached
+ </p>
+ </li>
+ </ul>
+ </li>
+ <li>Provide an implementation for <CODE>createEditPolicies()</CODE>,
+ during which <CODE>EditPolicy</CODE> implementations are associated with specific editing roles.
+ The <CODE>EditPolicy</CODE> and its associated roles, <CODE>Request</CODE> and
+ <CODE>Command</CODE> objects are a fundamental part of GEF which we discuss in the next sections
+ </li>
+</ol>
+
+<h3>Requests</h3>
+<p>
+We begin with requests because these are really the starting point of the editing process that GEF application developer works with.
+In fact, the real magic in GEF is being able to interpret user interactions and transform
+these into <B>requests</B>,
+which the application can work with in an object-oriented fashion.
+For example, when we drag from the "New Column" palette button onto an existing
+table on the diagram, we are of course trying to add a new column to the table.
+As users interact with the application, GEF's behind-the-scenes work produces <CODE>Request</CODE> objects.
+In the create column example, GEF produces
+a <CODE>CreateRequest</CODE>, which contains the following important information:
+<ul>
+ <li>the instance of the new model object that has been created
+ (but probably not yet configured and definitely not added to the rest of the model)</li>
+ <li>The <CODE>EditPart</CODE> object which is hosting this request.
+ In our case this will be an instance of <CODE>TablePart</CODE></li>
+</ul>
+Different types of user interactions will produce different <CODE>Request</CODE> types
+- these are well covered in the GEF API and platform documentation.
+These request objects neatly encapsulate the information the application needs to transform user interaction into changes to the model.
+We can take a look at how this is done once we have looked at <CODE>Commands</CODE> and <CODE>EditPolicies</CODE>,
+which we cover in the next section.
+
+
+
+<A NAME="editPolicies"></A>
+<h3>EditPolicies and Roles</h3>
+<p>
+An <CODE>EditPolicy</CODE> is really just an extension of an <CODE>EditPart</CODE>,
+in the sense that certain editing related tasks are passed on from the <CODE>EditPart</CODE> to its <CODE>EditPolicy</CODE> delegates.
+<CODE>EditPart</CODE> implementations would rapidly become bloated if they had to take on everything that <CODE>EditPolicies</CODE> do.
+To understand what an <CODE>EditPolicy</CODE> is and what it does,
+lets start by looking at the <CODE>createEditPolicies()</CODE> method in <CODE>TablePart</CODE>:
+<font color="#0000cc">
+<pre>protected void createEditPolicies()
+{
+ installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new TableNodeEditPolicy());
+ installEditPolicy(EditPolicy.LAYOUT_ROLE, new TableLayoutEditPolicy());
+ installEditPolicy(EditPolicy.CONTAINER_ROLE, new TableContainerEditPolicy());
+ installEditPolicy(EditPolicy.COMPONENT_ROLE, new TableEditPolicy());
+ installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE, new TableDirectEditPolicy());
+}</pre>
+</font>
+<p>
+The purpose of this method is simply to decorate the <CODE>TablePart</CODE> with editing functionality.
+Each call to <CODE>installEditPolicy()</CODE> in the above method
+registers an <CODE>EditPolicy</CODE> with the <CODE>EditPart</CODE>.
+The key constant used in each of these calls is the name of the <B>role</B> used.
+For example, <CODE>EditPolicy.CONTAINER_ROLE</CODE> is
+simply the string <I>"ContainerEditPolicy"</I>.
+The container role is relevant for <CODE>TablePart</CODE> because we know that tables contain
+columns, and one of our application's requirements is to create new columns
+and add these to existing tables.
+</p>
+<p>
+The use of a particular role name in the <CODE>installEditPolicy()</CODE> call is really just a convention - the framework does not
+attach any behavior to a particular choice of role name.
+What distinguishes an <CODE>EditPolicy</CODE> implementation (and its corresponding role) is the type of requests it understands.
+Most of the abstract <CODE>EditPolicy</CODE> classes
+provide an implementation of the <CODE>getCommand(Request request)</CODE> method.
+</p>
+<p>
+In <CODE>ContainerEditPolicy</CODE> we find the following:
+
+<font color="#0000cc">
+<pre>public Command getCommand(Request request) {
+ if (REQ_CREATE.equals(request.getType()))
+ return getCreateCommand((CreateRequest)request);
+ if (REQ_ADD.equals(request.getType()))
+ return getAddCommand((GroupRequest)request);
+ if (REQ_CLONE.equals(request.getType()))
+ return getCloneCommand((ChangeBoundsRequest)request);
+ if (REQ_ORPHAN_CHILDREN.equals(request.getType()))
+ return getOrphanChildrenCommand((GroupRequest)request);
+ return null;
+}</pre>
+</font>
+<p>
+Here <CODE>getCommand()</CODE> simply uses the request type to determine which <CODE>getXXXCommand()</CODE> method to call.
+In <CODE>ContainerEditPolicy</CODE>, <CODE>getCreateCommand()</CODE> is abstract -
+we must provide an implementation in order to use the base <CODE>ContainerEditPolicy</CODE> functionality.
+</p>
+<p>
+Here is our implementation of <CODE>TableContainerEditPolicy</CODE>:
+
+<font color="#0000cc">
+<pre>public class TableContainerEditPolicy extends ContainerEditPolicy
+{
+ protected Command getCreateCommand(CreateRequest request)
+ {
+ <img src="images/tag_1.gif" height=13 width=24 align=CENTER> Object newObject = request.getNewObject();
+ if (!(newObject instanceof Column))
+ {
+ return null;
+ }
+ Column column = (Column) newObject;
+
+ <img src="images/tag_2.gif" height=13 width=24 align=CENTER> TablePart tablePart = (TablePart) getHost();
+ Table table = tablePart.getTable();
+ <img src="images/tag_3.gif" height=13 width=24 align=CENTER> ColumnCreateCommand command = new ColumnCreateCommand();
+ command.setTable(table);
+ command.setColumn(column);
+ return command;
+ }
+}</pre>
+</font>
+<p>
+In most cases, our <CODE>EditPolicy</CODE> implementations simply amount to using a
+<CODE>Request</CODE> object to generate a <CODE>Command</CODE>.
+Our <CODE>getCreateCommand()</CODE> method
+<ul>
+ <li><img src="images/tag_1.gif" height=13 width=24 align=CENTER> gets the new object embodied in the <CODE>CreateRequest</CODE>
+ and makes sure that it is an instance of <CODE>Column</CODE>,</li>
+ <li><img src="images/tag_2.gif" height=13 width=24 align=CENTER> gets the <CODE>Table</CODE> object associated with
+ the host <CODE>EditPart</CODE>, and</li>
+ <li><img src="images/tag_3.gif" height=13 width=24 align=CENTER> creates an instance of the relevant <CODE>Command</CODE> class,
+ configures it with the <CODE>Table</CODE> and <CODE>Column</CODE> information, and returns it</li>
+</ul>
+Our <CODE>TablePart</CODE> <CODE>createEditPolicies()</CODE> implementation uses one of
+our customized <CODE>EditPolicy</CODE> implementations for each invocation of
+<CODE>installEditPolicy()</CODE>.
+Each of our <CODE>EditPolicy</CODE> implementations subclasses a GEF-provided abstract <CODE>EditPolicy</CODE> for a different role.
+For example, <CODE>TableEditPolicy</CODE> extends <CODE>ComponentEditPolicy</CODE> to
+fulfill the <CODE>EditPolicy.COMPONENT_ROLE</CODE>.
+It does so by implementing the
+<CODE>createDeleteCommand(GroupRequest request)</CODE> to handle requests of type <CODE>REQ_DELETE</CODE>.
+<p>
+The GEF platform documentation provides a lot more detail on the types of roles and requests and how and when they can be used,
+so we won't cover them in any more detail here.
+</p>
+<h3>Commands</h3>
+
+<p>
+<CODE>Command</CODE> is GEF's abstract base class whose function is simply to encapsulate our application's response to a request.
+Key methods included in the <CODE>Command</CODE> class are the following:
+<ul>
+ <li><CODE>execute()</CODE>:
+ <CODE>Command</CODE> provides a no-op implementation. As the name suggests,
+ this contains the code to apply any change to the model that the <CODE>Command</CODE> object encapsulates</li>
+ <li><CODE>undo()</CODE>: used to reverse the effect of <CODE>execute()</CODE>.
+ Here <CODE>Command</CODE> also provides a no-op implementation</li>
+ <li><CODE>redo()</CODE>: used redo a command execution.
+ The <CODE>Command</CODE> implementation simply calls <CODE>execute()</CODE>, which should usually be adequate</li>
+ <li><CODE>canExecute()</CODE>: whether <CODE>execute()</CODE> can be executed.
+ The subclass can implement this to specify the conditions under which the command can be executed</li>
+ <li><CODE>canUndo()</CODE>: whether <CODE>undo()</CODE> can be executed.
+ The <CODE>Command</CODE> implementation simply returns true, which subclasses can override</li>
+ <li><CODE>canRedo()</CODE>: whether <CODE>redo()</CODE> can be executed. The <CODE>Command</CODE> implementation here also simply returns true</li>
+</ul>
+<p>
+Any non-trivial <CODE>Command</CODE> subclass would need to implement <CODE>execute()</CODE>.
+Implementation of <CODE>undo()</CODE> would be recommended in most cases. The other methods
+are optional and would only be overridden as required.
+</p>
+<p>
+Lets take a look at our rather straightforward <CODE>ColumnCreateCommand</CODE> implementation:
+
+<font color="#0000cc">
+<pre>public class ColumnCreateCommand extends Command
+{
+ private Column column;
+ private Table table;
+
+ public void setColumn(Column column)
+ {
+ this.column = column;
+ <img src="images/tag_1.gif" height=13 width=24 align=CENTER> this.column.setName(&quot;COLUMN &quot; + (table.getColumns().size() + 1));
+ this.column.setType(Column.VARCHAR);
+ }
+
+ public void setTable(Table table)
+ {
+ this.table = table;
+ }
+
+ public void execute()
+ {
+ <img src="images/tag_2.gif" height=13 width=24 align=CENTER> table.addColumn(column);
+ }
+
+ public void undo()
+ {
+ <img src="images/tag_3.gif" height=13 width=24 align=CENTER> table.removeColumn(column);
+ }
+}</pre>
+</font>
+Much of the class is self-explanatory.
+We have setter methods to populate the <CODE>Command</CODE> object
+with the newly-created <CODE>Column</CODE> as well as the
+target container <CODE>Table</CODE>.
+We arbitrarily provide a name and type for the <CODE>Column</CODE> <img src="images/tag_1.gif" height=13 width=24 align=CENTER>,
+which the user can later change.
+We can also see that <CODE>execute()</CODE> <img src="images/tag_2.gif" height=13 width=24 align=CENTER>
+simply adds the <CODE>Column</CODE> object to the <CODE>Table</CODE>,
+and <CODE>undo()</CODE> <img src="images/tag_3.gif" height=13 width=24 align=CENTER> simply reverses that change.
+<p>
+The use of <CODE>Commands</CODE> has two key advantages over using <CODE>EditPolicies</CODE> directly to effect model changes
+<ul>
+ <li>Commands are more elegant and in line with OO best practice</li>
+ <li>The <CODE>Command</CODE> framework has built-in support for undo and redo functionality</li>
+</ul>
+<p>
+<img src="images/tip.gif" width="62" height="13"> The <CODE>Command</CODE> implementation is closely tied to the model,
+and should be cleanly separated from GEF-specific components.
+It should not contain any references to <CODE>EditParts</CODE> or <CODE>EditPolicies</CODE>.
+Observing this rule preserves the clean separation
+between commands and the UI logic, helping to keep code more maintainable and bug-free.
+</p>
+
+
+<h2>Propagating Model Changes</h2>
+
+<p>
+Once we've changed the model, our GEF editor needs to propagate these changes to the UI. Our model, view and controller need
+to work together to achieve this.
+</p>
+<p>
+So far, we have discussed the <CODE>GraphicalEditPart</CODE>'s responsibility to provide a figure
+to represent the part of the model it is managing.
+To participate in a fully functional graphical editor, it needs to do more:
+<ul>
+ <li>It needs to act as a <B>listener</B> for changes in the model.
+ The model itself needs to <B>fire event notifications</B> which the <CODE>EditPart</CODE> can receive</li>
+ <li>It needs to maintain its own
+ child and connection relationships with other <CODE>EditParts</CODE>, keeping these in sync with changes to the model</li>
+ <li>It needs to update the figures that it is managing, and their layouts, in line with model changes</li>
+</ul>
+We discuss each of these in turn.
+
+<h3>Sending and Receiving Event Notifications</h3>
+<p>
+The requirements imposed on our model implementation are that
+<ol>
+ <li>it exposes a mechanism by which listeners can register interest in event notifications, and</li>
+ <li>it actually fires these event notifications at the appropriate times!</li>
+</ol>
+In our example application we want all our model objects to use a common framework,
+so we satisfy the first requirement by
+allowing all our model classes to extend <CODE>PropertyAwareObject</CODE>, which looks like this:
+
+<font color="#0000cc">
+<pre>public abstract class PropertyAwareObject implements Serializable
+{
+
+<img src="images/tag_1.gif" height=13 width=24 align=CENTER> public static final String CHILD = &quot;CHILD&quot;;
+ ... other String constants representing the other types of model changes
+
+ <img src="images/tag_2.gif" height=13 width=24 align=CENTER> protected transient PropertyChangeSupport listeners = new PropertyChangeSupport(this);
+
+ protected PropertyAwareObject()
+ {
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener l)
+ {
+ <img src="images/tag_3.gif" height=13 width=24 align=CENTER> listeners.addPropertyChangeListener(l);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener l)
+ {
+ <img src="images/tag_4.gif" height=13 width=24 align=CENTER> listeners.removePropertyChangeListener(l);
+ }
+
+ protected void firePropertyChange(String prop, Object old, Object newValue)
+ {
+ <img src="images/tag_5.gif" height=13 width=24 align=CENTER> listeners.firePropertyChange(prop, old, newValue);
+ }
+
+ ...
+}</pre>
+</font>
+
+Our abstract model base class
+contains a few <CODE>String</CODE> constants <img src="images/tag_1.gif" height=13 width=24 align=CENTER>
+representing the types of model changes it knows about.
+It uses the <CODE>java.beans.PropertyChangeSupport</CODE> <img src="images/tag_2.gif" height=13 width=24 align=CENTER>
+to provide the "plumbing" for the event handling.
+It also exposes methods <img src="images/tag_3.gif" height=13 width=24 align=CENTER>
+and <img src="images/tag_4.gif" height=13 width=24 align=CENTER> which observers can use to register and deregister their
+interest in model changes.
+Finally, it includes a <CODE>firePropertyChange()</CODE> <img src="images/tag_5.gif" height=13 width=24 align=CENTER> method
+which subclasses can use to trigger property events.
+In our example of adding a column to a table, we see a good example in <CODE>Table</CODE>:
+
+<font color="#0000cc">
+<pre>public void addColumn(Column column)
+{
+ columns.add(column);
+ firePropertyChange(CHILD, null, column);
+}</pre>
+</font>
+
+With this mechanism available, we now need to take advantage in our <CODE>EditPart</CODE> listeners.
+Once again, we address the issue
+by providing a common base class for our <CODE>GraphicalEditParts</CODE> to extend, shown below:
+
+<font color="#0000cc">
+<pre>public abstract class PropertyAwarePart
+ extends AbstractGraphicalEditPart
+ implements PropertyChangeListener
+{
+ public void activate()
+ {
+ super.activate();
+ PropertyAwareObject propertyAwareObject = (PropertyAwareObject) getModel();
+ <img src="images/tag_1.gif" height=13 width=24 align=CENTER> propertyAwareObject.addPropertyChangeListener(this);
+ }
+
+ public void deactivate()
+ {
+ super.deactivate();
+ PropertyAwareObject propertyAwareObject = (PropertyAwareObject) getModel();
+ <img src="images/tag_2.gif" height=13 width=24 align=CENTER> propertyAwareObject.removePropertyChangeListener(this);
+ }
+
+ public void propertyChange(PropertyChangeEvent evt)
+ {
+ <img src="images/tag_3.gif" height=13 width=24 align=CENTER> //handle property change event
+ ...
+ }
+}</pre>
+</font>
+The GEF API documentation recommends the use of <CODE>activate()</CODE> and <CODE>deactivate()</CODE>
+to register or deregister model listeners.
+This is what we do here. After casting our model object to <CODE>PropertyAwareObject</CODE>,
+we add our <CODE>EditPart</CODE> as a listener in <img src="images/tag_1.gif" height=13 width=24 align=CENTER>,
+and allow it to be removed on deactivation in <img src="images/tag_2.gif" height=13 width=24 align=CENTER>.
+Once the <CODE>EditPart</CODE> is activated, any event notifications fired from our model
+will result in an invocation of <CODE>propertyChange()</CODE> <img src="images/tag_3.gif" height=13 width=24 align=CENTER>.
+Our <CODE>propertyChange()</CODE> implementation in <CODE>PropertyAwarePart</CODE> in turn delegates
+its response to other methods, which can be overridden by <CODE>EditPart</CODE> subclasses
+to customize reactions to specific changes in the model.
+
+<A NAME="synchronising"></A>
+<h3>Synchronizing EditPart Relationships with Model Changes</h3>
+<p>
+As we mentioned previously, the first thing the <CODE>EditPart</CODE> implementation needs to do in response to a model change is to
+ensure that its relationship hierarchy is in sync with that of the model.
+GEF provides a quick and easy solution in the form of three methods in the <CODE>EditPart</CODE>
+hierarchy. Before discussing
+a more performant approach that many applications will demand, we'll take a look at these methods.
+<ul>
+ <li><CODE>refreshChildren()</CODE>: when an <CODE>EditPart</CODE> represents a model object with children,
+ this method may need to be called.
+ Our example of adding a column to a table is a good one. The same applies for removing a column from a table.
+ If we moved a column from one table to another,
+ <CODE>refreshChildren()</CODE> would need to be called for both corresponding <CODE>TableParts</CODE>.
+ The base implementation of this method not only synchronizes your model and <CODE>EditPart</CODE> hierarchies -
+ it also adds or removes visual components as required
+ by calling the <CODE>AbstractGraphicalEditPart</CODE> <CODE>addChildVisual()</CODE> and <CODE>removeChildVisual()</CODE> methods
+ </li>
+ <li><CODE>refreshSourceConnections()</CODE>: this applies to any model change where the source of a connection
+ is added, removed or reassigned.
+ For example, if we added or deleted a primary/foreign key relationship, this method would need to be called
+ </li>
+ <li>
+ <CODE>refreshTargetConnections()</CODE>: this only applies to a model change where the target
+ of a connection is added, removed or reassigned. It would be needed for any change affecting
+ the primary key of a relationship between tables</li>
+</ul>
+<p>
+Returning to our example of adding a column to a table,
+our implementation of <CODE>PropertyAwarePart.propertyChange()</CODE> can be
+reduced to the following:
+<A NAME = "propertyChange"></A>
+<font color="#0000cc">
+<pre>public void propertyChange(PropertyChangeEvent evt)
+{
+ String property = evt.getPropertyName();
+
+ if (PropertyAwareObject.CHILD.equals(property))
+ {
+ <img src="images/tag_1.gif" height=13 width=24 align=CENTER> refreshChildren();
+ <img src="images/tag_2.gif" height=13 width=24 align=CENTER> refreshVisuals();
+ }
+ ... handle other types of property changes here
+
+}</pre>
+</font>
+
+To resynchronize the <CODE>EditPart</CODE> hierarchy, we simply call
+<CODE>refreshChildren()</CODE> <img src="images/tag_1.gif" height=13 width=24 align=CENTER>.
+To update the display, we then call <CODE>refreshVisuals()</CODE> <img src="images/tag_2.gif" height=13 width=24 align=CENTER>.
+We discuss the
+mechanics and rationale for <img src="images/tag_2.gif" height=13 width=24 align=CENTER>
+in the next section.
+<p>
+Using the methods <CODE>refreshChildren()</CODE>, <CODE>refreshSourceConnections()</CODE> and <CODE>refreshSourceConnections()</CODE>
+can help you get your application working quickly, but if we want our application to run <B>efficiently</B>,
+we need to be more selective
+in the methods we use. For example, to add or remove a child, we can use the <CODE>EditPart</CODE> methods
+<CODE>addChild(EditPart, int)</CODE> and <CODE>removeChild(EditPart)</CODE>.
+Our revised <CODE>handleChildChange(PropertyChangeEvent)</CODE>below is a better performing replacement for <CODE>refreshChildren()</CODE>
+which uses these methods:
+<font color="#0000cc">
+<pre>protected void handleChildChange(PropertyChangeEvent evt)
+{
+ Object newValue = evt.getNewValue();
+ Object oldValue = evt.getOldValue();
+
+ if (newValue != null)
+ {
+ //add new child
+ <img src="images/tag_1.gif" height=13 width=24 align=CENTER> EditPart editPart = createChild(newValue);
+ <img src="images/tag_2.gif" height=13 width=24 align=CENTER> int modelIndex = getModelChildren().indexOf(newValue);
+ <img src="images/tag_3.gif" height=13 width=24 align=CENTER> addChild(editPart, modelIndex);
+ }
+ else
+ {
+ //remove an existing child
+ List children = getChildren();
+
+ EditPart partToRemove = null;
+ for (Iterator iter = children.iterator(); iter.hasNext();)
+ {
+ EditPart part = (EditPart) iter.next();
+ if (part.getModel() == oldValue)
+ {
+ <img src="images/tag_4.gif" height=13 width=24 align=CENTER> partToRemove = part;
+ break;
+ }
+ }
+ if (partToRemove != null)
+ <img src="images/tag_5.gif" height=13 width=24 align=CENTER> removeChild(partToRemove);
+ }
+}</pre>
+</font>
+<p>
+When adding our child, we need to call <CODE>createChild()</CODE>
+<img src="images/tag_1.gif" height=13 width=24 align=CENTER> to get a new <CODE>EditPart</CODE> for the model child.
+We then find the index of the model child in the containing <CODE>List</CODE><img src="images/tag_2.gif" height=13 width=24 align=CENTER>,
+and add our new child <CODE>EditPart</CODE> using this index <img src="images/tag_3.gif" height=13 width=24 align=CENTER>.
+When removing a child, we iterate through the existing children
+<CODE>EditParts</CODE> until we find the one representing the removed model child <img src="images/tag_4.gif" height=13 width=24 align=CENTER>.
+We then remove this <CODE>EditPart</CODE> <img src="images/tag_5.gif" height=13 width=24 align=CENTER>.
+</p>
+<p>
+Clearly, there is more work here than in simply calling <CODE>refreshChildren()</CODE>: but for large models where performance is critical, this effort will be worth it.
+</p>
+<p>
+Interested readers can examine <CODE>handleInputChange(PropertyChangeEvent)</CODE> and <CODE>handleOuputChange(PropertyChangeEvent)</CODE> in
+<CODE>PropertyAwarePart</CODE>
+for similar alternatives to <CODE>refreshSourceConnections()</CODE> and <CODE>refreshTargetConnections()</CODE> when updating relationships.
+</p>
+
+<A NAME="viewUpdate"></A>
+<h3>Updating and Repainting the Display</h3>
+
+<p>
+Consider our example of adding a column to a table. In draw2d terms,
+this is represented by adding an <CODE>EditableLabel</CODE> into
+a <CODE>ColumnsFigure</CODE> instance, which is itself contained within a <CODE>TableFigure</CODE>.
+Both the <CODE>ColumnsFigure</CODE> and the <CODE>TableFigure</CODE> both need to enlarge
+- the result otherwise is ugly (take my word for it!).
+</p>
+<p>
+A few things need to happen:
+<ol>
+ <li>The cached information held by the layout managers for the <CODE>TableFigure</CODE> and <CODE>ColumnsFigure</CODE>,
+ which includes minimum size and preferred size for the child figures, needs to be thrown away</li>
+ <li>The <CODE>SchemaFigure</CODE>'s layout manager needs to
+ update any cached constraint information it is holding for the <CODE>TableFigure</CODE></li>
+ <li>The bounds of both the <CODE>TableFigure</CODE> and the <CODE>ColumnsFigure</CODE>
+ need to change to reflect addition of the column&nbsp;</li>
+ <li>Any area affected by the change needs to be repainted</li>
+</ol>
+
+<p>
+In fact, all we need to achieve this is in our implementation of <CODE>refreshVisuals()</CODE> in <CODE>TablePart</CODE>:
+
+<font color="#0000cc">
+<pre>protected void refreshVisuals()
+{
+ TableFigure tableFigure = (TableFigure) getFigure();
+<img src="images/tag_1.gif" height=13 width=24 align=CENTER> Point location = tableFigure.getLocation();
+ SchemaDiagramPart parent = (SchemaDiagramPart) getParent();
+<img src="images/tag_2.gif" height=13 width=24 align=CENTER> Rectangle constraint = new Rectangle(location.x, location.y, -1, -1);
+<img src="images/tag_3.gif" height=13 width=24 align=CENTER> parent.setLayoutConstraint(this, tableFigure, constraint);
+}</pre>
+</font>
+We get the
+location of our figure <img src="images/tag_1.gif" height=13 width=24 align=CENTER>,
+use this to provide a new <CODE>Rectangle</CODE> constraint object <img src="images/tag_2.gif" height=13 width=24 align=CENTER>.
+By setting the width and height to <B>-1</B>, we ensure that the preferred width and height are calculated automatically.
+We then pass on the constraint to the parent <CODE>EditPart</CODE>'s layout manager <img src="images/tag_3.gif" height=13 width=24 align=CENTER>.
+<p>
+That's all there is to it.
+
+
+
+
+
+But how do we know that the preferred size calculation for the
+<CODE>TableFigure</CODE> or <CODE>ColumnFigure</CODE>
+won't be using some stale cached value?
+If you're interested in the answers to questions like this, read the
+sidebar below.
+</p>
+<table border="1" cellpadding="4" width="90%" bgcolor="FFFFCC"><tr>
+ <td bgcolor="0080c0"><font size="+1" color="FFFFCC"><b>Sidebar: Invalidating and Updating Figures</b></font> </td>
+ </tr>
+<tr><td>
+<p>
+How does GEF know when to rearrange and resize figures, and which parts of the screen to repaint?
+The key is in the methods in the <CODE>IFigure</CODE> interface and in the behavior of the <B>update manager</B>:
+
+<ul>
+ <li>
+ <p>
+ <CODE>invalidate()</CODE>: each <CODE>Figure</CODE> instance has a <B>valid</B>
+ flag which can be set to <CODE>true</CODE> or <CODE>false</CODE>.
+ When <CODE>invalidate()</CODE> is called:
+ <ol>
+ <li>the valid flag for the figure is set to false (the figure becomes invalid)
+ </li>
+ <li><CODE>invalidate()</CODE> is called on the <CODE>Figure</CODE>'s layout manager.
+ Here, any cached preferred size information that the layout manager holds for the figure is thrown away
+ <br>
+ <br>
+ </li>
+ </ol>
+ The importance of the invalid state will become more clear when we discuss <CODE>validate()</CODE>.
+ </p>
+ </li>
+ <li>
+ <p>
+ <CODE>revalidate()</CODE>: this method is used to <CODE>invalidate()</CODE> a figure and its parent chain.
+ When called on a figure, this figure invalidates itself and then
+ calls its parent's <CODE>revalidate()</CODE> method.
+ The hierarchy's root figure (one with no parent) is finally placed on the update manager's queue of
+ <B>invalid root figures</B>,
+ that is, figures that need to be validated.
+ </p>
+ <p>
+ <CODE>revalidate()</CODE> is called automatically when changes to figures occur which are likely to affect the bounds of
+ parent figures.
+ Its role can be clearly seen in its usages in the <CODE>Figure</CODE> and <CODE>Label</CODE> classes draw2d package, shown below:
+<p>
+<img src="images/revalidate-s.JPG" height=274 width=259 align=CENTER>
+</p>
+<p>
+ In our example of adding a column label to a table, <CODE>revalidate()</CODE> is automatically called when the new column label is added to the
+ <CODE>ColumnsFigure</CODE> instance using the <CODE>IFigure.addFigure(IFigure, Object, int)</CODE> method.
+ This is why correct resizing of the table occurs without having to invalidate any figures in our
+ example's code.
+ </p>
+ <p>
+<p>
+<img src="images/tip.gif" width="62" height="13"> If no method is called which itself automatically invokes <CODE>revalidate()</CODE>,
+you may need to invoke this method yourself in your application code to correctly update the display.
+</p>
+ </p>
+ </li>
+ <li>
+ <p>
+ <CODE>repaint()</CODE>: in the same way that <CODE>revalidate()</CODE> queues a figure with the update manager for validating,
+ this method queues the figure's bounds as a <I>dirty region</I> for repainting.
+ Like <CODE>revalidate()</CODE>, this method is automatically called in many places in draw2d, such as when the size of a figure changes.
+ You are most likely to need to call this method in your application code if implementing custom subclasses of <CODE>Figure</CODE>.
+ </p>
+ </li>
+ <li>
+ <p>
+ <CODE>validate()</CODE>: this finishes the job that <CODE>revalidate()</CODE> started.
+ The update manager calls <CODE>validate()</CODE> on each of the invalid root figures on the queue.
+ During the <CODE>validate()</CODE> execution the following happens:
+ <ol>
+ <li>the figure's valid flag is set back to true</li>
+ <li>layout takes place - if the figure has a layout manager
+ then its <CODE>layout()</CODE>
+ method is called
+ </li>
+ <li>
+ the figure then validates each of its invalid children
+ </li>
+ <br>
+ </ol>
+ The value of <CODE>revalidate()</CODE> is in helping to ensure that
+ only figures that <I>need</I> to participate in the validate and layout process
+ can be correctly flagged as invalid before this process begins.
+ </p>
+ <p>
+ After validating its invalid root figures, the update manager will repaint the enclosing rectangle for regions marked as <I>dirty</I>
+ via the <CODE>repaint()</CODE> method.
+ </p>
+ </li>
+</ul>
+</p>
+</td></tr></table>
+
+<h2>Conclusion</h2>
+<p>
+We've covered quite a lot of ground in this article.
+Most significantly, we've talked about how you can use the
+basic building blocks of a GEF application to easily build an application which adheres to a clean MVC design.
+With the exception of the direct editing functionality, most
+of the other types of editing operations work in a very similar way to the simple column adding example presented.
+Of course, all of the building blocks need to be put together in the
+context of an Eclipse editor. Space limitations preclude any discussion of these
+topics, but interested readers can peruse the source code, as well as that of the official GEF examples,
+to see how this can be done.
+</p>
+<p>
+For more information on GEF, look at the Eclipse platform documentation,
+available via Eclipse online help if you download and install the GEF SDK.
+<a href="http://www-106.ibm.com/developerworks/opensource/library/os-gef/" target="_blank">How to Get Started with the GEF</a>
+ gives a good introduction to GEF basics. <a href="../Article-GEF-Draw2d/GEF-Draw2d.html">Display a UML Diagram using Draw2D</a>
+ is a good starting point for those unfamiliar with Eclipse draw2d. <a href="http://publib-b.boulder.ibm.com/Redbooks.nsf/RedbookAbstracts/sg246302.html?Open" target="_blank">
+ Eclipse Development using the Graphical Editing Framework and the Eclipse Modeling Framework</a>
+ is an IBM Redbook providing more detailed coverage of GEF and EMF.
+ You will also need to install EMF to get the Redbook examples to work.
+</p>
+<h2>Acknowledgements</h2>
+<p>
+Thanks to Randy Hudson and Jim des Rivières for their thorough and careful reviews,
+which have been very helpful in improving both the technical accuracy and readability of
+this article.
+<h2>Source Code</h2>
+<p> To run the example or view the source code for this article, download and
+ unzip <a href="schemaeditor.zip">schemaeditor.zip</a> into your <i>eclipse/</i>
+ subdirectory. Note that you will need Eclipse 3.0 or later to run the examples.</p>
+
+</body>
+</html>
diff --git a/Article-GEF-editor/images/Idea.jpg b/Article-GEF-editor/images/Idea.jpg
new file mode 100644
index 0000000..119ce70
--- /dev/null
+++ b/Article-GEF-editor/images/Idea.jpg
Binary files differ
diff --git a/Article-GEF-editor/images/editor.JPG b/Article-GEF-editor/images/editor.JPG
new file mode 100644
index 0000000..d6785a4
--- /dev/null
+++ b/Article-GEF-editor/images/editor.JPG
Binary files differ
diff --git a/Article-GEF-editor/images/layout.gif b/Article-GEF-editor/images/layout.gif
new file mode 100644
index 0000000..2f7185f
--- /dev/null
+++ b/Article-GEF-editor/images/layout.gif
Binary files differ
diff --git a/Article-GEF-editor/images/revalidate-s.JPG b/Article-GEF-editor/images/revalidate-s.JPG
new file mode 100644
index 0000000..9fe9515
--- /dev/null
+++ b/Article-GEF-editor/images/revalidate-s.JPG
Binary files differ
diff --git a/Article-GEF-editor/images/revalidate.JPG b/Article-GEF-editor/images/revalidate.JPG
new file mode 100644
index 0000000..bbf3de4
--- /dev/null
+++ b/Article-GEF-editor/images/revalidate.JPG
Binary files differ
diff --git a/Article-GEF-editor/images/tag_1.gif b/Article-GEF-editor/images/tag_1.gif
new file mode 100644
index 0000000..4859d6f
--- /dev/null
+++ b/Article-GEF-editor/images/tag_1.gif
Binary files differ
diff --git a/Article-GEF-editor/images/tag_2.gif b/Article-GEF-editor/images/tag_2.gif
new file mode 100644
index 0000000..5ea43dc
--- /dev/null
+++ b/Article-GEF-editor/images/tag_2.gif
Binary files differ
diff --git a/Article-GEF-editor/images/tag_3.gif b/Article-GEF-editor/images/tag_3.gif
new file mode 100644
index 0000000..a69b68e
--- /dev/null
+++ b/Article-GEF-editor/images/tag_3.gif
Binary files differ
diff --git a/Article-GEF-editor/images/tag_4.gif b/Article-GEF-editor/images/tag_4.gif
new file mode 100644
index 0000000..a1ad63f
--- /dev/null
+++ b/Article-GEF-editor/images/tag_4.gif
Binary files differ
diff --git a/Article-GEF-editor/images/tag_5.gif b/Article-GEF-editor/images/tag_5.gif
new file mode 100644
index 0000000..d86a748
--- /dev/null
+++ b/Article-GEF-editor/images/tag_5.gif
Binary files differ
diff --git a/Article-GEF-editor/images/tag_6.gif b/Article-GEF-editor/images/tag_6.gif
new file mode 100644
index 0000000..b9eb4ec
--- /dev/null
+++ b/Article-GEF-editor/images/tag_6.gif
Binary files differ
diff --git a/Article-GEF-editor/images/tag_7.gif b/Article-GEF-editor/images/tag_7.gif
new file mode 100644
index 0000000..5f0e8fa
--- /dev/null
+++ b/Article-GEF-editor/images/tag_7.gif
Binary files differ
diff --git a/Article-GEF-editor/images/tip.gif b/Article-GEF-editor/images/tip.gif
new file mode 100644
index 0000000..77b2451
--- /dev/null
+++ b/Article-GEF-editor/images/tip.gif
Binary files differ
diff --git a/Article-GEF-editor/images/tryit.gif b/Article-GEF-editor/images/tryit.gif
new file mode 100644
index 0000000..f4927a4
--- /dev/null
+++ b/Article-GEF-editor/images/tryit.gif
Binary files differ
diff --git a/Article-GEF-editor/schemaeditor.zip b/Article-GEF-editor/schemaeditor.zip
new file mode 100644
index 0000000..e21b0b7
--- /dev/null
+++ b/Article-GEF-editor/schemaeditor.zip
Binary files differ
diff --git a/Article-Image-Viewer/Image_viewer.html b/Article-Image-Viewer/Image_viewer.html
new file mode 100644
index 0000000..3a9d9fd
--- /dev/null
+++ b/Article-Image-Viewer/Image_viewer.html
@@ -0,0 +1,831 @@
+<html>
+
+<head>
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
+<title>A basic image viewer</title>
+<link rel="stylesheet" href="../default_style.css">
+</head>
+
+<body LINK="#0000ff" VLINK="#800080">
+<div align="right">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; Copyright
+ &copy; 2004 Chengdong Li
+ <table border=0 cellspacing=0 cellpadding=2 width="100%">
+ <tr>
+ <td align=LEFT valign=TOP colspan="2" bgcolor="#0080C0"><b><font color="#FFFFFF">&nbsp;Eclipse
+ Corner Article</font></b></td>
+ </tr>
+ </table>
+</div>
+<div align="left">
+ <h1><img src="images/Idea.jpg" height=86 width=120 align=CENTER></h1>
+</div>
+<p>&nbsp;</p>
+
+<h1 ALIGN="CENTER">A Basic Image Viewer</h1>
+
+<blockquote>
+<b>Summary</b>
+
+<br>
+This article shows how to extend SWT <code>Canvas</code> to implement a mini image viewer plug-in using Java2D
+transforms. The
+extended image canvas can be used to scroll and zoom large images, and can also
+be extended to apply other transforms. The implementation is based on SWT and
+the non-UI portions of AWT. The plug-in has been tested on Windows, Linux GTK, and Mac
+OS X Carbon with Eclipse 2.1 or better.
+<p><b> By Chengdong
+Li (</b><a href="mailto:cdli@ccs.uky.edu">cdli@ccs.uky.edu</a><b>)
+Research in Computing for Humanities, University of Kentucky <br>
+</b>
+March 15, 2004</p>
+</blockquote>
+
+<hr width="100%">
+<h2>Contents</h2>
+<ul>
+ <li><a href="#Introduction">Introduction</a></li>
+ <li><a href="#Overview">Classes overview</a></li>
+ <li><a href="#Implement_Canvas">Canvas implementation</a>
+ <ul>
+ <li><a href="#Loading_image">Loading images</a></li>
+ <li><a href="#Extending_Canvas">Extending org.eclipse.swt.widgets.Canvas</a></li>
+ <li><a href="#Rendering_image">Rendering images</a></li>
+ <li><a href="#Transformation">Transformations</a></li>
+ <li><a href="#Synchronize_scrollbar">Scrollbar synchronization</a></li>
+ </ul>
+ </li>
+ <li><a href="#Rotating">Rotation</a></li>
+ <li><a href="#Plug-in_Implementation">Plug-in implementation</a>
+ <ul>
+ <li><a href="#Create_view_plug-in">Create view plug-in</a></li>
+ <li><a href="#Add_viewActions_extension">Add viewActions extension</a></li>
+ </ul>
+ </li>
+ <li><a href="#Summary">Summary</a></li>
+ <li><a href="#Acknowledge">Acknowledgements</a></li>
+ <li><a href="#Reference">References</a></li>
+</ul>
+<h2>Conventions &amp; Terms</h2>
+<p>The following typographic conventions are used in this article:</p>
+<p><i>Italic</i>:<br>
+&nbsp;&nbsp;&nbsp; Used for references to articles.</p>
+<code>Courier New:</code><br>
+&nbsp;&nbsp;&nbsp; Used for code or variable names.
+<p>The following terms are used in this article:</p>
+<p><b>client area<br>
+</b>&nbsp;&nbsp;&nbsp; The
+drawable area of canvas. Also called the <b>paint area</b> or <b>canvas domain</b>.<br>
+<b>source image</b><br>
+&nbsp;&nbsp;&nbsp; The image constructed directly from
+the original image data with the same width and height. Unlike image data, it is
+device dependent. It is the <code> sourceImage</code> in source
+code. Also called the <b>original image</b> or <b>image domain</b>.</p>
+<h2><a name="Introduction">Introduction</a></h2>
+<p> The goal of this article is to show you how to implement an image viewer with
+scrolling and zooming operations using affine transforms.
+If you are new to graphics in SWT, please read Joe Winchester's article <i><a href="http://www.eclipse.org/articles/Article-SWT-images/graphics-resources.html">Taking a look at SWT Images</a></i>.
+A screenshot of the image viewer is shown in Figure 1:</p>
+<p><img border="0" src="images/screen_shot.jpg" width="359" height="318"><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Figure 1 - Image viewer</p>
+<p>The implementation here is different from the implementation of the Image Analyzer example
+that comes with Eclipse. This implementation uses affine transforms for scrolling and zooming.</p>
+<p>The advantages of this implementation are :</p>
+<ul>
+ <li>it offers unlimited zoom scale</li>
+ <li>it works well for large images</li>
+</ul>
+<p>In the following sections, we will first review the structure of the package
+and relationship of classes,
+then we will discuss how the image canvas works and how to implement a scrollable
+and zoom-able image canvas - <code> SWTImageCanvas</code>. We will use
+affine transforms to selectively render images and to generally simplify the implementation. After that, we will show
+briefly how to use the local toolbar to facilitate image&nbsp; manipulation.</p>
+<p>For the detailed steps on how to implement a view, Dave Springgay's
+ article: <i><a href="http://www.eclipse.org/articles/viewArticle/ViewArticle2.html">Creating
+an Eclipse View</a></i> is the most helpful one.</p>
+<p>You can compare this implementation with the Image Analyzer example by running both of
+them:</p>
+<ul>
+ <li>To run the example for this article unzip <a href="imageviewer.zip">
+imageviewer.zip</a> into your <i>eclipse/plugins/ </i>subdirectory and restart
+ Eclipse. To open the image
+viewer view, choose Window -&gt; Show View -&gt; Other -&gt; Sample Category -&gt;
+Image Viewer. The source plug-in project is imageviewersrc.zip which is included inside the <a href="imageviewer.zip">
+imageviewer.zip</a>.</li>
+ <li>To run the Image Analyzer example that comes with Eclipse, download the Example
+Plug-ins from <a href="http://www.eclipse.org/downloads/index.php">Eclipse.org</a>,
+and unzip to the <i>eclipse/plugins/</i> subdirectory and restart Eclipse. Then choose Window -&gt; Show
+View -&gt; Other -&gt; SWT Example Launcher -&gt; Standalone -&gt; Image
+Analyzer.</li>
+</ul>
+<p>To compile and run the image viewer from source code, unzip the imageviewersrc.zip
+file (inside <a href="imageviewer.zip">
+imageviewer.zip</a>), then import the existing project into the workspace, update the
+class path, compile, and run.</p>
+<h2><a name="Overview">Classes Overview</a></h2>
+<p>The following diagram (Figure 2) shows all classes in this demo plug-in. The <code> SWTImageCanvas</code> is a subclass of
+<code>org.eclipse.swt.widgets.Canvas</code>;
+it implements image loading, rendering, scrolling, and zooming. The <code> ImageView</code> class is a subclass of
+<code>
+org.eclipse.ui.part.ViewPart</code>; it has an <code> SWTImageCanvas</code> instance. The helper class
+<code>SWT2Dutil</code> holds utility
+functions. <code> PushActionDelegate</code> implements <code>
+org.eclipse.ui.IViewActionDelegate</code>; it delegates the toolbar button actions,
+and has an <code>ImageView</code> instance. The <code>
+ImageViewerPlugin</code> extends <code> org.eclipse.ui.plugin.AbstractUIPlugin</code>
+(this class is PDE-generated).</p>
+<p><img border="0" src="images/all_classes.jpg" width="640" height="308"><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Figure 2 - Class diagram ( The classes without package prefix are implemented
+in our approach. )</p>
+<p>A plug-in manifest file plugin.xml defines the runtime requirements and contributions (view and
+viewActions extensions) to
+Eclipse. Eclipse will create toolbar buttons
+for <code> ImageView</code> and delegate toolbar actions via <code> PushActionDelegate</code>.</p>
+<h2><a name="Implement_Canvas">Canvas implementation</a></h2>
+<p> <code> SWTImageCanvas</code> handles image loading,
+painting, scrolling, and
+zooming. It saves a copy of the original SWT image (the <code> sourceImage</code>)
+in memory, and then translates and scales
+the image using <code>java.awt.geom.AffineTransform</code>. The
+rendering and transformation are applied only to the portion of the image
+visible on the
+screen, allowing it to operate on images of any size with good performance. The <code> AffineTransform</code>
+ gets applied changes as the user scrolls the window and pushes the toolbar buttons.</p>
+<h4><a name="Loading_image">Loading images</a>&nbsp;</h4>
+<p>First, let's have a look at how to load an image into memory. There are several ways to load an
+image:</p>
+<ul>
+ <li> load an image from the local file system.</li>
+ <li> load an image from the workspace.&nbsp;</li>
+ <li>load an image from a website.</li>
+</ul>
+<p>In this simple implementation, we only allow the user to choose an image from
+the local file
+system. To improve this, you could contribute to the <code>org.eclipse.ui.popupMenus</code>
+of the Navigator view for image files; that way, whenever an image file is selected, the menu item will be available and
+the user can choose to load the image
+from the workspace (you need add <code>nameFilters</code>, and you may also need to use workspace
+API). To see how to load an image from a URL, please refer to
+the Image Analyzer of SWT
+examples.</p>
+<p>The image loading process is as following (Figure 3):</p>
+<p align="left"><img border="0" src="images/open_activity.jpg" width="402" height="255"><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Figure 3 - Image-loading diagram</p>
+<p>Now let's take a look at the code for loading images.&nbsp;</p>
+<p>SWT
+provides <code> ImageLoader</code> to load an image into memory.
+Image loading is done by using the <code>Image(Display,String)</code> constructor. To facilitate image loading, we provides a
+dialog to locate all image files supported by SWT <code> ImageLoader</code>.&nbsp;</p>
+<pre><b>public</b> <b>void</b> onFileOpen(){
+ FileDialog fileChooser = <b>new</b> FileDialog(getShell(), SWT.OPEN);
+ fileChooser.setText(&quot;Open image file&quot;);
+<img src="images/tag_1.gif" height=13 width=24 align=CENTER> fileChooser.setFilterPath(currentDir);
+ fileChooser.setFilterExtensions(
+ <b>new</b> String[] { &quot;*.gif; *.jpg; *.png; *.ico; *.bmp&quot; });
+ fileChooser.setFilterNames{
+ <b>new</b> String[] { &quot;SWT image&quot; + &quot; (gif, jpeg, png, ico, bmp)&quot; });
+ String filename = fileChooser.open();
+ if (filename != <b>null</b>){
+<img src="images/tag_2.gif" height=13 width=24 align=CENTER> loadImage(filename);
+<img src="images/tag_3.gif" height=13 width=24 align=CENTER> currentDir = fileChooser.getFilterPath();
+ }
+}<b>
+public</b> Image loadImage(String filename) {
+ <b>if</b>(sourceImage!=<b>null</b> &amp;&amp; !sourceImage.isDisposed()){
+ sourceImage.dispose();
+ sourceImage=<b>null</b>;
+ }
+<img src="images/tag_4.gif" height=13 width=24 align=CENTER> sourceImage= <b>new</b> Image(getDisplay(),filename);
+<img src="images/tag_5.gif" height=13 width=24 align=CENTER> showOriginal();
+ <b>return</b> sourceImage;
+}</pre>
+<p>We use <code>currentDir</code> in <img src="images/tag_1.gif" height=13 width=24 align=CENTER>
+ and <img src="images/tag_3.gif" height=13 width=24 align=CENTER>
+to remember the directory for the file open dialog, so that the user can later open other files
+in the same directory.</p>
+<p>The <code>loadImage</code> method (shown above) in <img src="images/tag_2.gif" height=13 width=24 align=CENTER>
+ disposes the old <code> sourceImage</code> and creates a new <code>sourceImage</code>,
+then it calls the <code>showOriginal()</code> to notify the canvas to
+paint new image. If loading fails, the canvas will clear the painting area
+and disable the scrollbar. Notice that we cannot see <code>ImageLoader</code>
+directly in the code above, however, when we call <code>Image(Display,
+String)</code> in
+<img src="images/tag_4.gif" height=13 width=24 align=CENTER>, Eclipse will call
+<code>ImageLoader.load()</code> to
+load the image into memory. <img src="images/tag_5.gif" height=13 width=24 align=CENTER>
+is used to show the image at its original size; we will
+discuss this in more detail <a href="#func_showOriginal">later</a>.</p>
+<p><img src="images/tip.gif" width="62" height="13"> In fact, the above two functions
+could be merged into one method. The reason why we separate them is we
+may invoke them separately from other functions; for example, we may get the image file
+name from the database, then we can reload the image by only calling <code>loadImage()</code>.</p>
+<h4><a name="Extending_Canvas">Extending org.eclipse.swt.widgets.Canvas</a></h4>
+<p>Now, let's see how to create a canvas to render the image and do some
+transformations.</p>
+<p>The <code>org.eclipse.swt.widgets.Canvas</code>
+ is suitable to be extended for rendering images. <code>SWTImageCanvas</code>
+extends it and adds scrollbars. This is done by setting the <code>SWT.V_SCROLL</code>
+and <code>SWT.H_SCROLL</code> style bits at the <code>Canvas</code>
+constructor:</p>
+<pre><b>public</b> SWTImageCanvas(<b>final</b> Composite parent, <b>int</b> style) {
+<img src="images/tag_1.gif" height=13 width=24 align=CENTER> <b>super</b>(parent,style|SWT.BORDER|SWT.V_SCROLL|SWT.H_SCROLL
+ |SWT.NO_BACKGROUND);
+<img src="images/tag_2.gif" height=13 width=24 align=CENTER> addControlListener(<b>new</b> ControlAdapter() { <font color="#3f7f5f">/* resize listener */</font>
+ <b>public</b> <b>void</b> controlResized(ControlEvent event) {
+ syncScrollBars();
+ }
+ });
+<img src="images/tag_3.gif" height=13 width=24 align=CENTER> addPaintListener(<b>new</b> PaintListener() { <font color="#3f7f5f">/* paint listener */</font>
+ <b>public</b> <b>void</b> paintControl(PaintEvent event) {
+ paint(event.gc);
+ }
+ });
+<img src="images/tag_4.gif" height=13 width=24 align=CENTER> initScrollBars();
+}<b>
+private</b> <b>void</b> initScrollBars() {
+ ScrollBar horizontal = getHorizontalBar();
+ horizontal.setEnabled(<b>false</b>);
+ horizontal.addSelectionListener(<b>new</b> SelectionAdapter() {<b>
+ public</b> <b>void</b> widgetSelected(SelectionEvent event) {
+ scrollHorizontally((ScrollBar) event.widget);
+ }
+ });
+ ScrollBar vertical = getVerticalBar();
+ vertical.setEnabled(<b>false</b>);
+ vertical.addSelectionListener(<b>new</b> SelectionAdapter() {<b>
+ public</b> <b>void</b> widgetSelected(SelectionEvent event) {
+ scrollVertically((ScrollBar) event.widget);
+ }
+ });
+}</pre>
+<p><img src="images/tip.gif" width="62" height="13"> In order to speed up the
+rendering process and reduce flicker, we set the style to <code>SWT.NO_BACKGROUND</code>
+in <img src="images/tag_1.gif" height=13 width=24 align=CENTER>
+(and later we use <a href="#double-buffering">double buffering</a> to render) so that the background (client area) won't be cleared.
+The new image will be
+overlapped on the background. We need to fill the gaps between the new image and
+the background when the new image does not fully cover the background.</p>
+<p><img src="images/tag_2.gif" height=13 width=24 align=CENTER> registers a
+resize listener to synchronize the
+size and position of the scrollbar thumb to the image zoom scale and
+translation; <img src="images/tag_3.gif" height=13 width=24 align=CENTER>
+registers a paint listener (here it does <code>paint(GC gc)</code>)
+to render the image whenever the <code>PaintEvent</code>
+is fired; <img src="images/tag_4.gif" height=13 width=24 align=CENTER>
+registers the <code>SelectionListener</code>
+for each scrollbar,
+the <code>SelectionListener</code>
+ will notify <code>SWTImageCanvas</code> to scroll and zoom
+the image based on the current selection of scrollbars; another function of the <code>SelectionListener</code>
+ is to enable or disable the scrollbar based on the image size and zoom scale.&nbsp;</p>
+<h4><a name="Rendering_image">Rendering images</a></h4>
+<p>Whenever the SWT<code> PaintEvent</code> is fired, the paint listener (<code>paint(GC
+gc)</code>)
+will be called to paint the
+damaged area. In this article, we simply paint the whole client area of the
+canvas (see Figure 4).
+Since we support scrolling and zooming, we need to figure out which part of
+the original image should be drawn to which part of the client area. The painting process is as
+following:</p>
+<ol>
+ <li>Find a rectangle <code>imageRect</code> inside the source
+ image (<b>image domain</b>); the image inside this rectangle will be drawn to the client area of canvas (<b>canvas
+ domain</b>).</li>
+ <li>Map the <code>imageRect</code> to the client area and
+ get <code>destRect</code>.</li>
+ <li>Draw the source image within <code>imageRect</code> to <code>destRect</code>
+ (scaling it if the sizes are different).</li>
+ <li>Fill the gaps (shown as blue and green bands in the picture below) if
+ necessary.</li>
+</ol>
+<p><a name="Rendering_scenario_figure"></a><img border="0" src="images/render_model.jpg" width="656" height="426">&nbsp;&nbsp;&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Figure 4 - Rendering scenarios</p>
+<p>1) and 2) can be done based on <code>AffineTransform</code>, which we will discuss next.&nbsp;</p>
+<p>3) draws a part of the source image to the client area using GC's <code>drawImage</code>:<br>
+<code> &nbsp;&nbsp;&nbsp; drawImage
+(Image&nbsp;image, int&nbsp;srcX, int&nbsp;srcY, int&nbsp;srcWidth, int&nbsp;srcHeight,
+int&nbsp;destX, int&nbsp;destY, int&nbsp;destWidth, int&nbsp;destHeight)</code></p>
+<p>which copies a rectangular area from the source image into a destination rectangular
+area and automatically scale the
+image if the source rectangular area has a different size from the destination
+rectangular area.</p>
+<p>If we draw the image directly on the screen, we need to calculate the gaps in
+4) and fill them. Here we make use of <a href="#double-buffering"> double
+buffering</a>, so the gaps will be filled
+automatically.</p>
+<p><img src="images/tip.gif" width="62" height="13">We use the following
+approach to render the image: We save only the source image. When the canvas needs to update the visible area,
+it copies the corresponding image area from the source image to the destination area on
+the canvas. This approach can
+offer a very large zoom scale and save the memory, since it does not
+need to save the whole big zoomed image. The drawing process is also speeded up.
+If the size of canvas is very huge, we could divide the canvas into several small
+grids, and render each grid using our approach; so this approach is to some extent scalable.</p>
+<p><img border="0" src="images/note.gif" width="62" height="13">The Image Analyzer example
+that comes with Eclipse draws the whole
+zoomed image, and scrolls the zoomed image (which is saved by system) to the right place based on the
+scrollbar positions. This implementation works well for small images, or when the zoom
+scale is not
+large. However,
+for large-sized images and zoom scale greater than 1, the scrolling becomes very
+slow since it has to operate on a very large zoomed image. This can be shown in
+Image Analyzer.</p>
+<p>Now let's look at the code used to find out the corresponding rectangles in the
+source image and the client area:</p>
+<pre><b>private</b> <b>void</b> paint(GC gc) {
+<b>1</b> Rectangle clientRect = getClientArea(); <font color="#3f7f5f">/* canvas' painting area */</font>
+<b>2</b> <b>if</b> (sourceImage != <b>null</b>) {
+<b>3</b> Rectangle imageRect=SWT2Dutil.inverseTransformRect(transform, clientRect);
+<b>4</b>
+<b>5</b> <b>int</b> gap = 2; <font color="#3f7f5f">/* find a better start point to render. */</font>
+<b>6</b> imageRect.x -= gap; imageRect.y -= gap;
+<b>7</b> imageRect.width += 2 * gap; imageRect.height += 2 * gap;
+<b>8</b>
+<b>9 </b>Rectangle imageBound=sourceImage.getBounds();
+<b>10</b> imageRect = imageRect.intersection(imageBound);
+<b>11</b> Rectangle destRect = SWT2Dutil.<a href="#transformRect">transformRect</a>(transform, imageRect);
+<b>12</b>
+<b>13</b> <b>if</b> (screenImage != <b>null</b>){screenImage.dispose();}
+<b>14</b> screenImage = <b>new</b> Image( getDisplay(),clientRect.width, clientRect.height);
+<b>15</b> GC newGC = <b>new</b> GC(screenImage);
+<b>16</b> newGC.setClipping(clientRect);
+<b>17</b> newGC.drawImage( sourceImage,
+<b>18</b> imageRect.x,
+<b>19</b> imageRect.y,
+<b>20</b> imageRect.width,
+<b>21</b> imageRect.height,
+<b>22</b> destRect.x,
+<b>23</b> destRect.y,
+<b>24</b> destRect.width,
+<b>25</b> destRect.height);<b>
+26 </b>newGC.dispose();<b>
+27
+28</b> gc.drawImage(screenImage, 0, 0);<b>
+29</b> } <b>else</b> {
+<b>30</b> gc.setClipping(clientRect);
+<b>31</b> gc.fillRectangle(clientRect);
+<b>32</b> initScrollBars();
+<b>33</b> }
+}</pre>
+<p>Line 3 to line 10 are used to find a rectangle (<code>imageRect</code>) in the source image, the source image inside
+this rectangle will be drawn to the canvas. This is done by inverse
+transforming the canvas's client area to the image domain and intersecting it with the bounds of image. The
+<code>imageRect</code>
+of line 10 is the exact rectangle we need.
+Once we have got <code>imageRect</code>,
+we transform <code>imageRect</code> back to the canvas domain in
+line 11 and get a rectangle <code>destRect</code> inside
+the client area. The source image inside the <code>imageRect</code> will be
+drawn to the client area inside <code>destRect</code>.</p>
+<p>After we get the <code>imageRect</code> of the source
+image and the corresponding <code>destRect</code> of the
+client area, we can draw just the part of image to be shown, and draw it in the right place.
+For convenience, here we use <a name="double-buffering"> double buffering</a> to ease the drawing process:
+we first create a <code>screenImage</code> and draw image to
+the <code>screenImage</code>, then copy the <code>screenImage</code>
+to the canvas.</p>
+<p>Line 30 to line 32 are used to clear the canvas and reset the scrollbar whenever the
+source image is set to null.</p>
+<p><img src="images/tip.gif" width="62" height="13">Line 5 to line 7 are used to
+find a better point to start drawing the rectangular image, since the transform may compress or
+enlarge the size of each pixel. To make the scrolling and zooming
+smoothly, we always draw the image from the beginning of a pixel. This also guarantee
+that the image always fills the canvas if it is larger than the canvas.</p>
+<p>The flowchart of rendering is as following (Figure 5):</p>
+<p><img border="0" src="images/render_flowchart.jpg" width="677" height="209"><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Figure 5 - Rendering flowchart</p>
+<p>In the code above, we use <code>inverseTransformRect()</code>
+in line 3 and <code>transformRect()</code> in line 11 for
+transforming rectangles between different domain. We will discuss them in detail in
+the next section.</p>
+<h4><a name="Transformation">Transformations</a></h4>
+<p><img border="0" src="images/note.gif" width="62" height="13"> When we say scrolling in this
+section, we mean scrolling the image, not the scrollbar thumb (which actually moves
+in the opposite direction).</p>
+<p>Our primary goal is to develop a canvas with scrolling and zooming functions. To
+do
+that, we must solve the following problems:</p>
+<ul>
+ <li>How to save the scrolling and zooming parameters.</li>
+ <li>How to change the scrolling and zooming parameters.</li>
+ <li>How the scrolling and zooming parameters control the image rendering.</li>
+</ul>
+<p>Scrolling and zooming entails two transformations: translation and scaling (see
+Figure 6).
+Translation is used to change the horizontal and
+vertical position of the image; scrolling involves translating the image in the
+horizontal or vertical directions. Scaling is used to change the size of image;
+scale with a rate
+greater than 1 to zoom in; scale with a rate less than 1 to zoom out.</p>
+<p><img border="0" src="images/transform.jpg" width="333" height="145"><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Figure 6 - Translation and scaling</p>
+<p><code>SWTImageCanvas</code> uses an <code> AffineTransform</code> to
+save the parameters of both the translation and
+the scaling. In this implementation, only translation and scaling are
+used. The basic idea of <code> AffineTransform</code> is to represent the transform as a matrix and
+then merge several transforms into one by matrix multiplication. For
+example, a scaling <b>S</b> followed by a translation <b>T </b>can be merged into
+a transform like: <b>T</b>*<b>S</b>. By merging first and then
+transforming, we can reduce times for transforming
+and speed up the process.</p>
+<p><code>SWTImageCanvas</code> has an <code>AffineTransform</code>
+instance transform:</p>
+<pre><b> private</b> AffineTransform transform;</pre>
+<p><code>AffineTransform</code> provides
+methods to access the translation and scaling parameters of an affine
+transform:</p>
+<pre> <b>public double</b> getTranslateX();
+ <b>public double</b> getTranslateY();
+ <b>public double</b> getScaleX();
+ <b>public double</b> getScaleY();</pre>
+<p>To change the <code>AffineTransform</code>, we can either reconstruct an <code>AffineTransform</code>
+by merging itself
+and another transform, or start from scratch. <code>AffineTransform</code> provides
+<code>preConcatenate()</code> and <code>concatenate()</code>
+ methods, which can merge two <code>AffineTransform</code>s
+into one. Using these two methods, each time the user scrolls or
+zooms the image, we can create a new transform based on the changes (scrolling
+changes translation and zooming changes scaling) and the transform itself. The
+merge operation is matrix multiplication. Since 2D <code>AffineTransform</code> uses&nbsp;a 3x3 matrix, so the computation is very cheap.</p>
+<p> For
+example, when the user scrolls the image by <b>tx</b> in the x direction and<b>
+ty </b> in the y
+direction:</p>
+<pre>&nbsp;&nbsp;&nbsp; newTransform = oldTransform.preconcatenate(AffineTransform.getTranslateInstance(<b>tx</b>,<b>ty</b>));&nbsp;</pre>
+<p>To construct a scaling or translation transform from scratch:</p>
+<pre> <b>static</b> AffineTransform getScaleInstance(sx, sy);
+ <b>static</b> AffineTransform getTranslateInstance(tx,ty);</pre>
+<p> Once you have an <code>AffineTransform</code>, the transformation can be easily done.
+To transform a point:</p>
+<pre>&nbsp;&nbsp;&nbsp; <b>public static</b> Point transformPoint(AffineTransform af, Point pt) {
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point2D src = <b>new</b> Point2D.Float(pt.x, pt.y);
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point2D dest= af.transform(src, <b>null</b>);
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point point=<b>new</b> Point((int)Math.floor(dest.getX()),(int)Math.floor(dest.getY()));
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>return</b> point;
+&nbsp;&nbsp;&nbsp; }</pre>
+<p>To get the inverse transform of a point:</p>
+<pre> <b>static</b> Point2D inverseTransform(Point2D&nbsp;ptSrc, Point2D&nbsp;ptDst);</pre>
+<p>Since we use only translation and scaling in our implementation,
+transforming a rectangle can be done by first transforming the top-left point,
+and then scaling the width and height. To do that, we need to convert an arbitrary
+rectangle to a rectangle with positive width and length. The following code
+shows how to transform an arbitrary rectangle using <code>AffineTransform</code>
+(the inverse transform is almost the same):</p>
+<pre><b>1</b>&nbsp;&nbsp; <b>public static</b> Rectangle <a name="transformRect">transformRect</a>(AffineTransform af, Rectangle src){
+<b>2</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rectangle dest= <b>new</b> Rectangle(0,0,0,0);
+<b>3</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; src=absRect(src);
+<b>4</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point p1=<b>new</b> Point(src.x,src.y);
+<b>5</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p1=transformPoint(af,p1);
+<b>6</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dest.x=p1.x; dest.y=p1.y;
+<b>7</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dest.width=(<b>int</b>)(src.width*af.getScaleX());
+<b>8</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dest.height=(<b>int</b>)(src.height*af.getScaleY());
+<b>9</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b>return</b> dest;
+<b>10</b> &nbsp;}</pre>
+<p>The <code>absRect()</code> function in line 3 is used to
+convert an arbitrary rectangle to a rectangle with positive width and height.</p>
+<p>For more detail about <code>AffineTransform</code>, you can
+read <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/awt/geom/AffineTransform.html"> the
+Java API document from SUN website</a>.</p>
+<p><img src="images/tip.gif" width="62" height="13"> <code>AffineTransform</code>
+also supports shear and rotation. In this
+article, we only need translation and scaling. <code> AffineTransform</code> is widely used in the AWT's
+image packages, and it has no relation with UI event loop, so it can be used in
+SWT. (Even if <code>AffineTransform</code> were unavailable,&nbsp; we could easily replace or rewrite it since we only use the translation and
+scaling).</p>
+<p>We have seen how we save the scrolling and scaling parameters in <code>AffineTransform</code>,
+and how we can change them. But how do they control the image rendering?</p>
+<p><img border="0" src="images/scroll_zoom_activity.jpg" width="540" height="149"><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Figure 7 - Scrolling and zooming diagram</p>
+<p>The basic idea is shown in Figure 7. When the user interacts with GUI
+(scrollbars and toolbar buttons), her/his action will be caught by Eclipse, Eclipse will
+invoke the listeners (for scrollbars) or delegates (for toolbar buttons) to change the parameters in
+the transform,
+then the canvas will update the status of scrollbars based on the transform,
+and finally it will notify itself to repaint the image. The painter
+will consider the updated transform when it
+repaints the image. For
+example, it will use transform to find out the corresponding rectangle in the source
+image to the visible
+area on the canvas, and copy
+the source image inside the rectangle to the canvas with scaling.</p>
+<p>Let's take a look at some methods which use <code>AffineTransform</code>
+to translate and zoom images.</p>
+<p>First let's see how to show an image at its original size:</p>
+<pre><b><a name="func_showOriginal"></a>public</b> <b>void</b> showOriginal() {<b>
+</b><img src="images/tag_1.gif" height=13 width=24 align=CENTER><b> </b>transform=<b>new</b> AffineTransform();
+ syncScrollBars();
+}</pre>
+<p>Here we first change transform in <img src="images/tag_1.gif" height=13 width=24 align=CENTER>
+ (defaults to a scaling rate of 1, and no translation), and then call <code>syncScrollBars()</code> to update the
+scrollbar and repaint the canvas. It's that simple.</p>
+<p>Now let's try another one - zooming. When we zoom the image, we will zoom it around the center of
+the client
+area (centered zooming). The procedure for centered zooming is:</p>
+<ol>
+ <li>Find the center of client area: (x,y).</li>
+ <li>Translate the image by (-x,-y), so that (x,y) is at the origin.</li>
+ <li>Scale the image.</li>
+ <li>Translate the image by (x,y).</li>
+</ol>
+<p>The <a href="#func_syncScrollBars">syncScrollBars</a>()
+ (see next section) guarantees that the image will be centered in the client
+area if it is smaller than the client area.</p>
+<p>Steps 2-4 can be used to scale images around an arbitrary point (dx,dy).
+Since the same steps will be used by many other methods, we put them in the method
+<code>centerZoom(dx,dy,scale,af)</code>:&nbsp;</p>
+<pre><b>public</b> <b>void</b> centerZoom(<b>double</b> dx,<b>double</b> dy,<b>double</b> scale,AffineTransform af) {
+ af.preConcatenate(AffineTransform.getTranslateInstance(-dx, -dy));
+ af.preConcatenate(AffineTransform.getScaleInstance(scale, scale));
+ af.preConcatenate(AffineTransform.getTranslateInstance(dx, dy));
+ transform=af;
+ syncScrollBars();
+}</pre>
+<p> Now the code for <code>zoomIn</code>
+is:</p>
+<pre><b>public</b> <b>void</b> zoomIn() {
+ <b>if</b> (sourceImage == <b>null</b>) <b>return</b>;
+ Rectangle rect = getClientArea();<b>
+</b> <b>int</b> w = rect.width, h = rect.height;
+ <font color="#3f7f5f">/* zooming center */</font>
+ <b>double</b> dx = ((<b>double</b>) w) / 2;
+ <b>double</b> dy = ((<b>double</b>) h) / 2;
+ centerZoom(dx, dy, ZOOMIN_RATE, transform);
+}</pre>
+<p>Here the (<code>dx</code>,<code>dy</code>) is the zooming center, <code>ZOOMIN_RATE</code>
+is a constant for incremental zooming in. <code>centerZoom()</code> will also call
+<code>syncScrollBars()</code>
+to update the scrollbar and repaint the canvas.</p>
+<h4><a name="Synchronize_scrollbar">Scrollbar synchronization</a></h4>
+<p>Each time user zooms or scrolls the image, the scrollbars need to update
+themselves to synchronize with the state of image. This includes adjusting the position and the size of the
+thumbs,
+enabling or disabling the scrollbars, changing the range of the scrollbars, and
+finally notifying the canvas to repaint the client area. We use <code>syncScrollBars()</code>
+to do this:</p>
+<pre><b><a name="func_syncScrollBars"></a>public</b> <b>void</b> syncScrollBars() {
+<img src="images/tag_1.gif" height=13 width=24 align=CENTER> <b>if</b> (sourceImage == <b>null</b>){
+ redraw();
+ <b>return</b>;
+ }
+ AffineTransform af = transform;<b>
+</b> <b>double</b> sx = af.getScaleX(), sy = af.getScaleY();
+ <b>double</b> tx = af.getTranslateX(), ty = af.getTranslateY();
+<img src="images/tag_2.gif" height=13 width=24 align=CENTER> <b>if</b> (tx &gt; 0) tx = 0; <b>if</b> (ty &gt; 0) ty = 0;
+
+ ScrollBar horizontal = getHorizontalBar();
+ horizontal.setIncrement((<b>int</b>)(getClientArea().width/100));
+ horizontal.setPageIncrement(getClientArea().width);<b>
+</b> Rectangle imageBound = swtImage.getBounds();<b>
+</b> <b>int</b> cw = getClientArea().width, ch = getClientArea().height;
+ <b>if</b> (imageBound.width * sx &gt; cw) { <font color="#3f7f5f">/* image is wider than client area */</font>
+ horizontal.setMaximum((<b>int</b>) (imageBound.width * sx));
+ horizontal.setEnabled(<b>true</b>);
+ <b>if</b> (((<b>int</b>) - tx) &gt; horizontal.getMaximum()-cw) {
+ tx = -horizontal.getMaximum()+cw;
+ }
+ } <b>else</b> { <font color="#3f7f5f">/* image is narrower than client area */</font>
+ horizontal.setEnabled(<b>false</b>);
+<img src="images/tag_3.gif" height=13 width=24 align=CENTER> tx = (cw - imageBound.width * sx) / 2;
+ }
+<img src="images/tag_4.gif" height=13 width=24 align=CENTER> horizontal.setSelection((<b>int</b>) (-tx));
+<img src="images/tag_5.gif" height=13 width=24 align=CENTER> horizontal.setThumb((<b>int</b>)(getClientArea().width));
+
+ <font color="#3f7f5f">/* update vertical scrollbar, same as above. */</font>
+ ScrollBar vertical = getVerticalBar();
+ ....
+ <font color="#3f7f5f">/* update transform. */</font>
+<img src="images/tag_6.gif" height=13 width=24 align=CENTER> af = AffineTransform.getScaleInstance(sx, sy);
+ af.preConcatenate(AffineTransform.getTranslateInstance(tx, ty));
+ transform=af;
+
+<img src="images/tag_7.gif" height=13 width=24 align=CENTER> redraw();
+}</pre>
+<p>If there is no image, the paint listener will be
+notified to clear the client area in <img src="images/tag_1.gif" height=13 width=24 align=CENTER>.</p>
+<p>If there is an image to show, we correct the current translation to make sure it's legal (&lt;=0).
+The
+point (<code>tx</code>,<code>ty</code>) in <img src="images/tag_2.gif" height=13 width=24 align=CENTER>
+corresponds to the bottom-left corner of the zoomed image (see the right-hand
+image in <a href="#Rendering_scenario_figure">Figure 4</a>), so it's
+reasonable to make it no larger than zero (the bottom-left corner of the canvas
+client area is (0,0)) except if the zoomed image is smaller than the client
+area. In such a situation, we correct the transform in <img src="images/tag_3.gif" height=13 width=24 align=CENTER>
+so that it will translate the
+image to the center of client area. We change the selection in <img src="images/tag_4.gif" height=13 width=24 align=CENTER>
+and the thumb size in <img src="images/tag_5.gif" height=13 width=24 align=CENTER>,
+so that the horizontal scrollbar will show the relative position to the whole
+image exactly.
+The other lines between&nbsp;<img src="images/tag_2.gif" height=13 width=24 align=CENTER>
+and <img src="images/tag_5.gif" height=13 width=24 align=CENTER>
+set the GUI parameters for the horizontal scrollbar, you can change them to
+control the scrolling increment. The
+process for the vertical scrollbar is exactly the same, so we don't show
+it here. Lines between
+<img src="images/tag_6.gif" height=13 width=24 align=CENTER>
+and <img src="images/tag_7.gif" height=13 width=24 align=CENTER>
+create a new transform based on the corrected translation and
+the scaling and update the old transform. Finally, line <img src="images/tag_7.gif" height=13 width=24 align=CENTER>
+notifies the canvas to repaint itself.</p>
+<h2><a name="Rotating">Rotation</a></h2>
+<p>Joe Winchester's <i><a href="http://www.eclipse.org/articles/Article-SWT-images/graphics-resources.html">Taking a look at SWT Images</a></i>
+explains pixel manipulation in
+great detail. Here
+we will show how to rearrange the pixels to get a 90<sup>0 </sup>counter-clockwise
+rotation. In order to demonstrate how other
+classes can interact with <code>SWTImageCanvas</code>, we put
+the implementation in the <code>PushActionDelegate</code> class. The basic steps for our rotation are:</p>
+<ul>
+ <li>Get image data from <code>SWTImageCanvas</code>.</li>
+ <li> Create new image data and rearrange the pixels.</li>
+ <li>Set new image data back to <code>SWTImageCanvas</code>.</li>
+</ul>
+<p>The code in <code>PushActionDelegate</code>
+for rotation is:</p>
+<pre> ImageData src=imageCanvas.getImageData();
+ <b>if</b>(src==<b>null</b>) <b>return</b>;
+ PaletteData srcPal=src.palette;
+ PaletteData destPal;
+ ImageData dest;
+
+ <font color="#3f7f5f">/* construct a new ImageData */</font>
+ <b>if</b>(srcPal.isDirect){
+<img src="images/tag_1.gif" height=13 width=24 align=CENTER> destPal=<b>new</b> PaletteData(srcPal.redMask,srcPal.greenMask,srcPal.blueMask);
+ }<b>else</b>{
+<img src="images/tag_2.gif" height=13 width=24 align=CENTER> destPal=<b>new</b> PaletteData(srcPal.getRGBs());
+ }
+<img src="images/tag_3.gif" height=13 width=24 align=CENTER> dest=<b>new</b> ImageData(src.height,src.width,src.depth,destPal);
+ <font color="#3f7f5f">/* rotate by rearranging the pixels */</font>
+ <b>for</b>(<b>int</b> i=0;i&lt;src.width;i++){<b>
+</b> <b>for</b>(<b>int</b> j=0;j&lt;src.height;j++){
+ <b>int</b> pixel=src.getPixel(i,j);
+<img src="images/tag_4.gif" height=13 width=24 align=CENTER> dest.setPixel(j,src.width-1-i,pixel);
+ }
+ }
+<img src="images/tag_5.gif" height=13 width=24 align=CENTER> imageCanvas.setImageData(dest);</pre>
+<p>The code for <code>setImageData()</code> is:</p>
+<pre><b>public</b> <b>void</b> setImageData(ImageData data) {
+ <b>if</b> (sourceImage != <b>null</b>) sourceImage.dispose();
+ <b>if</b>(data!=<b>null</b>)
+ sourceImage = <b>new</b> Image(getDisplay(), data);
+ syncScrollBars();
+}</pre>
+<p>Since we won't change the pixel value, we needn't care about
+the RGB of each pixel. However, we must reconstruct a new <code>ImageData</code> object with different dimension. This
+needs different <code>PaletteData</code> in <img src="images/tag_1.gif" height=13 width=24 align=CENTER>
+and <img src="images/tag_2.gif" height=13 width=24 align=CENTER>
+for different image formats.&nbsp;<img src="images/tag_3.gif" height=13 width=24 align=CENTER>
+creates a new <code>ImageData</code> and <img src="images/tag_4.gif" height=13 width=24 align=CENTER>
+sets the value of each pixel. <code>setImageData()</code> in <img src="images/tag_5.gif" height=13 width=24 align=CENTER>
+ will dispose the previous <code>sourceImage</code>
+and reconstruct <code>sourceImage</code>
+based on the new <code>ImageData</code>, then update the scrollbars
+and repaint the canvas. We put <code>setImageData()</code>
+inside <code>SWTImageCanvas</code> so it could be used
+by other methods in the future.</p>
+<h2><a name="Plug-in_Implementation">Plug-in Implementation</a></h2>
+<p>We have known how the image canvas works. Now, let's talk briefly about how to implement the plug-in.</p>
+<h3><a name="Create_view_plug-in">Step 1. Create view plug-in</a></h3>
+<p>Follow the steps 1-3 in <a href="http://www.eclipse.org/articles/viewArticle/ViewArticle2.html"><i>Creating
+an Eclipse View</i></a>, we can create a plug-in with a
+single view. The plugin.xml is:</p>
+<pre>&lt;plugin id=&quot;uky.article.imageviewer&quot;
+ name=&quot;image viewer Plug-in&quot;
+ version=&quot;1.0.0&quot;
+ provider-name=&quot;Chengdong Li&quot;
+ class=&quot;uky.article.imageviewer.ImageViewerPlugin&quot;&gt;
+ &lt;runtime&gt;
+ &lt;library name=&quot;imageviewer.jar&quot;/&gt;
+ &lt;/runtime&gt;
+ &lt;requires&gt;
+ &lt;import plugin=&quot;org.eclipse.ui&quot;/&gt;
+ &lt;/requires&gt;
+
+ &lt;extension point=&quot;org.eclipse.ui.views&quot;&gt;
+ &lt;category name=&quot;Sample Category&quot;
+ id=&quot;uky.article.imageviewer&quot;&gt;
+ &lt;/category&gt;
+ &lt;view name=&quot;Image Viewer&quot;
+ icon=&quot;icons/sample.gif&quot;
+ category=&quot;uky.article.imageviewer&quot;
+ class=&quot;uky.article.imageviewer.views.ImageView&quot;
+ id=&quot;uky.article.imageviewer.views.ImageView&quot;&gt;
+ &lt;/view&gt;
+ &lt;/extension&gt;
+&lt;/plugin&gt;</pre>
+<p>The <code>ImageViewerPlugin</code>
+and <code>ImageView</code>
+ are as following:</p>
+<b>
+<pre>public class </b>ImageViewerPlugin<b> extends </b>AbstractUIPlugin {
+<b> public </b>ImageViewerPlugin(IPluginDescriptor descriptor) {
+ <b>super</b>(descriptor);
+ }
+}
+<b>
+public</b> <b>class</b> ImageView <b>extends</b> ViewPart {
+<img src="images/tag_1.gif" height=13 width=24 align=CENTER> <b>public</b> SWTImageCanvas imageCanvas;<b>
+ public</b> ImageView() {} <b>
+ public</b> <b>void</b> createPartControl(Composite frame) {
+<img src="images/tag_2.gif" height=13 width=24 align=CENTER> imageCanvas=<b>new</b> SWTImageCanvas(frame);
+ }
+ <b>public</b> <b>void</b> setFocus() {
+<img src="images/tag_3.gif" height=13 width=24 align=CENTER> imageCanvas.setFocus();
+ }
+ <b>public</b> <b>void</b> dispose() {
+<img src="images/tag_4.gif" height=13 width=24 align=CENTER> imageCanvas.dispose();
+ <b>super</b>.dispose();
+ }
+}</pre>
+<p><img src="images/tag_1.gif" height=13 width=24 align=CENTER>
+ declares an instance variable <code>imageCanvas</code>
+to point to an instance of <code>SWTImageCanvas</code>,
+so that other methods can use it. <img src="images/tag_2.gif" height=13 width=24 align=CENTER>
+creates an <code>SWTImageCanvas</code> to show the image.
+When the view gets focus, it will set focus to <code>imageCanvas</code>
+in <img src="images/tag_3.gif" height=13 width=24 align=CENTER>.
+The dispose method of <code>SWTImageCanvas</code>
+ will be automatically called in&nbsp;<img src="images/tag_4.gif" height=13 width=24 align=CENTER>
+whenever the view is disposed.</p>
+<h3><a name="Add_viewActions_extension">Step 2. Add viewActions extension</a></h3>
+<p>The image viewer view has five local toolbar buttons: <img border="0" src="images/buttons.jpg" width="138" height="22">. To
+take the advantage of Eclipse, we&nbsp;contribute to the <code>org.eclipse.ui.viewActions</code>
+extension point by adding the following lines to plugin.xml:</p>
+<pre>&lt;extension point=&quot;org.eclipse.ui.viewActions&quot;&gt;
+ &lt;viewContribution
+ targetID=&quot;uky.article.imageviewer.views.ImageView&quot;
+ id=&quot;uky.article.imageviewer.views.ImageView.pushbutton&quot;&gt;
+ &lt;action label=&quot;open&quot;
+ icon=&quot;icons/Open16.gif&quot;
+ tooltip=&quot;Open image&quot;
+<img src="images/tag_1.gif" height=13 width=24 align=CENTER> class=&quot;uky.article.imageviewer.actions.PushActionDelegate&quot;
+ toolbarPath=&quot;push_group&quot;
+ enablesFor=&quot;*&quot;
+ id=&quot;toolbar.open&quot;&gt;
+ &lt;/action&gt;
+ .....
+&lt;/viewContribution&gt;</pre>
+<p>The delegate class <code>PushActionDelegate</code>
+ in <img src="images/tag_1.gif" height=13 width=24 align=CENTER>
+ will process all the actions from the
+toolbar buttons. It is defined as following:</p>
+<b>
+<pre>public</b> <b>class</b> PushActionDelegate <b>implements</b> IViewActionDelegate {
+<img src="images/tag_2.gif" height=13 width=24 align=CENTER> <b>public</b> ImageView view;<b>
+</b> <b>public</b> <b>void</b> init(IViewPart viewPart) {
+ <b>if</b>(viewPart <b>instanceof</b> ImageView){
+<img src="images/tag_3.gif" height=13 width=24 align=CENTER> <b>this</b>.view=(ImageView)viewPart;
+ }
+ }<b>
+ public</b> <b>void</b> run(IAction action) {
+ String id=action.getId();
+<img src="images/tag_4.gif" height=13 width=24 align=CENTER> SWTImageCanvas imageCanvas=view.imageCanvas;
+ <b>if</b>(id.equals(&quot;toolbar.open&quot;)){
+ imageCanvas.onFileOpen();
+ <b>return</b>;
+ }
+ ....
+<b> if</b>(id.equals(&quot;toolbar.zoomin&quot;)){
+ ....
+ }
+ }
+}</pre>
+<p>This class implements the <code>IViewActionDelegate</code> interface. It has a view instance in <img src="images/tag_2.gif" height=13 width=24 align=CENTER>.
+It gets the view instance during the initialization period<img src="images/tag_3.gif" height=13 width=24 align=CENTER>,
+and later in <img src="images/tag_4.gif" height=13 width=24 align=CENTER>
+it uses the view instance to interact with the <code>SWTImageCanvas</code>.&nbsp;</p>
+<h2><a name="Summary">Summary</a></h2>
+<p>We have shown the detail on how to implement a simple image viewer plug-in for
+Eclipse. The <code>SWTImageCanvas</code> supports scrolling
+and zooming functions by using AWT's <code>AffineTransform</code>. It supports unlimited
+zoom scale and smooth scrolling even for large images.</p>
+<p>Compared with the implementation of Image Analyzer example, this implementation is
+both memory
+efficient and fast.</p>
+<p>The <code>SWTImageCanvas</code> can be used as a base
+class for rendering, scrolling, and scaling image.</p>
+<p>Shortcut keys are a must for usable image viewers. In the interest of space, we did not show
+this here; however, they can be easily added.</p>
+<h2><a name="Acknowledge">Acknowledgements</a></h2>
+<p>I appreciate the help I received from the <a href="http://dev.eclipse.org/newslists/news.eclipse.platform.swt/msg00951.html"> Eclipse mailing
+list</a>; the Eclipse
+team's help in reviewing&nbsp; the article; Pengtao Li's photo picture; and
+finally the support from <a href="http://www.rch.uky.edu">RCH</a> lab at the
+University of Kentucky.</p>
+<h2><a name="Reference">Reference</a>s</h2>
+<p><a href="http://www.eclipse.org/articles/viewArticle/ViewArticle2.html">Creating
+an Eclipse View</a>. Dave Springgay, 2001 <a href="http://www.eclipse.org/articles/viewArticle/ViewArticle2.html"><br>
+</a>
+<a href="http://www.eclipse.org/articles/Article-SWT-images/graphics-resources.html">Taking a look at SWT
+Images</a>. Joe Winchester, 2003 <a href="http://www.eclipse.org/articles/Article-SWT-images/graphics-resources.html"><br>
+</a>
+<a href="http://www.amazon.com/exec/obidos/tg/detail/-/0321159640/103-6992553-2927029?v=glance">
+The Java Developer's Guide to ECLIPSE</a>. Sherry Shavor, Jim D'Anjou, Scott
+Fairbrother, Dan Kehn, John Kellerman, Pat McCarthy. Addison-Wesley, 2003
+
+</body>
+</html>
diff --git a/Article-Image-Viewer/images/Idea.jpg b/Article-Image-Viewer/images/Idea.jpg
new file mode 100644
index 0000000..119ce70
--- /dev/null
+++ b/Article-Image-Viewer/images/Idea.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/activity.bmp b/Article-Image-Viewer/images/activity.bmp
new file mode 100644
index 0000000..4520973
--- /dev/null
+++ b/Article-Image-Viewer/images/activity.bmp
Binary files differ
diff --git a/Article-Image-Viewer/images/allClass.jpg b/Article-Image-Viewer/images/allClass.jpg
new file mode 100644
index 0000000..bb9e058
--- /dev/null
+++ b/Article-Image-Viewer/images/allClass.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/all_classes.jpg b/Article-Image-Viewer/images/all_classes.jpg
new file mode 100644
index 0000000..bb9e058
--- /dev/null
+++ b/Article-Image-Viewer/images/all_classes.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/buttons.bmp b/Article-Image-Viewer/images/buttons.bmp
new file mode 100644
index 0000000..172b9e9
--- /dev/null
+++ b/Article-Image-Viewer/images/buttons.bmp
Binary files differ
diff --git a/Article-Image-Viewer/images/buttons.jpg b/Article-Image-Viewer/images/buttons.jpg
new file mode 100644
index 0000000..0102845
--- /dev/null
+++ b/Article-Image-Viewer/images/buttons.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/flower.jpg b/Article-Image-Viewer/images/flower.jpg
new file mode 100644
index 0000000..e8e5321
--- /dev/null
+++ b/Article-Image-Viewer/images/flower.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/gap.bmp b/Article-Image-Viewer/images/gap.bmp
new file mode 100644
index 0000000..eb8d01c
--- /dev/null
+++ b/Article-Image-Viewer/images/gap.bmp
Binary files differ
diff --git a/Article-Image-Viewer/images/linux_only.gif b/Article-Image-Viewer/images/linux_only.gif
new file mode 100644
index 0000000..7c135cf
--- /dev/null
+++ b/Article-Image-Viewer/images/linux_only.gif
Binary files differ
diff --git a/Article-Image-Viewer/images/model.bmp b/Article-Image-Viewer/images/model.bmp
new file mode 100644
index 0000000..f9f6246
--- /dev/null
+++ b/Article-Image-Viewer/images/model.bmp
Binary files differ
diff --git a/Article-Image-Viewer/images/note.gif b/Article-Image-Viewer/images/note.gif
new file mode 100644
index 0000000..e015c95
--- /dev/null
+++ b/Article-Image-Viewer/images/note.gif
Binary files differ
diff --git a/Article-Image-Viewer/images/open.bmp b/Article-Image-Viewer/images/open.bmp
new file mode 100644
index 0000000..14ec49b
--- /dev/null
+++ b/Article-Image-Viewer/images/open.bmp
Binary files differ
diff --git a/Article-Image-Viewer/images/open1.bmp b/Article-Image-Viewer/images/open1.bmp
new file mode 100644
index 0000000..1572b8d
--- /dev/null
+++ b/Article-Image-Viewer/images/open1.bmp
Binary files differ
diff --git a/Article-Image-Viewer/images/open_activity.jpg b/Article-Image-Viewer/images/open_activity.jpg
new file mode 100644
index 0000000..0551001
--- /dev/null
+++ b/Article-Image-Viewer/images/open_activity.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/paint.bmp b/Article-Image-Viewer/images/paint.bmp
new file mode 100644
index 0000000..acb626d
--- /dev/null
+++ b/Article-Image-Viewer/images/paint.bmp
Binary files differ
diff --git a/Article-Image-Viewer/images/render_flowchart.jpg b/Article-Image-Viewer/images/render_flowchart.jpg
new file mode 100644
index 0000000..53c66ac
--- /dev/null
+++ b/Article-Image-Viewer/images/render_flowchart.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/render_model.jpg b/Article-Image-Viewer/images/render_model.jpg
new file mode 100644
index 0000000..fa41b38
--- /dev/null
+++ b/Article-Image-Viewer/images/render_model.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/screen_shot.jpg b/Article-Image-Viewer/images/screen_shot.jpg
new file mode 100644
index 0000000..0c27751
--- /dev/null
+++ b/Article-Image-Viewer/images/screen_shot.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/scroll_zoom_activity.jpg b/Article-Image-Viewer/images/scroll_zoom_activity.jpg
new file mode 100644
index 0000000..058986c
--- /dev/null
+++ b/Article-Image-Viewer/images/scroll_zoom_activity.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/tag_1.gif b/Article-Image-Viewer/images/tag_1.gif
new file mode 100644
index 0000000..4859d6f
--- /dev/null
+++ b/Article-Image-Viewer/images/tag_1.gif
Binary files differ
diff --git a/Article-Image-Viewer/images/tag_2.gif b/Article-Image-Viewer/images/tag_2.gif
new file mode 100644
index 0000000..5ea43dc
--- /dev/null
+++ b/Article-Image-Viewer/images/tag_2.gif
Binary files differ
diff --git a/Article-Image-Viewer/images/tag_3.gif b/Article-Image-Viewer/images/tag_3.gif
new file mode 100644
index 0000000..a69b68e
--- /dev/null
+++ b/Article-Image-Viewer/images/tag_3.gif
Binary files differ
diff --git a/Article-Image-Viewer/images/tag_4.gif b/Article-Image-Viewer/images/tag_4.gif
new file mode 100644
index 0000000..a1ad63f
--- /dev/null
+++ b/Article-Image-Viewer/images/tag_4.gif
Binary files differ
diff --git a/Article-Image-Viewer/images/tag_5.gif b/Article-Image-Viewer/images/tag_5.gif
new file mode 100644
index 0000000..d86a748
--- /dev/null
+++ b/Article-Image-Viewer/images/tag_5.gif
Binary files differ
diff --git a/Article-Image-Viewer/images/tag_6.gif b/Article-Image-Viewer/images/tag_6.gif
new file mode 100644
index 0000000..b9eb4ec
--- /dev/null
+++ b/Article-Image-Viewer/images/tag_6.gif
Binary files differ
diff --git a/Article-Image-Viewer/images/tag_7.gif b/Article-Image-Viewer/images/tag_7.gif
new file mode 100644
index 0000000..5f0e8fa
--- /dev/null
+++ b/Article-Image-Viewer/images/tag_7.gif
Binary files differ
diff --git a/Article-Image-Viewer/images/tip.gif b/Article-Image-Viewer/images/tip.gif
new file mode 100644
index 0000000..77b2451
--- /dev/null
+++ b/Article-Image-Viewer/images/tip.gif
Binary files differ
diff --git a/Article-Image-Viewer/images/transform.bmp b/Article-Image-Viewer/images/transform.bmp
new file mode 100644
index 0000000..28dc072
--- /dev/null
+++ b/Article-Image-Viewer/images/transform.bmp
Binary files differ
diff --git a/Article-Image-Viewer/images/transform.jpg b/Article-Image-Viewer/images/transform.jpg
new file mode 100644
index 0000000..8c170bd
--- /dev/null
+++ b/Article-Image-Viewer/images/transform.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/tryit.gif b/Article-Image-Viewer/images/tryit.gif
new file mode 100644
index 0000000..f4927a4
--- /dev/null
+++ b/Article-Image-Viewer/images/tryit.gif
Binary files differ
diff --git a/Article-Image-Viewer/images/viewer.jpg b/Article-Image-Viewer/images/viewer.jpg
new file mode 100644
index 0000000..0c27751
--- /dev/null
+++ b/Article-Image-Viewer/images/viewer.jpg
Binary files differ
diff --git a/Article-Image-Viewer/images/win_only.gif b/Article-Image-Viewer/images/win_only.gif
new file mode 100644
index 0000000..895f9ca
--- /dev/null
+++ b/Article-Image-Viewer/images/win_only.gif
Binary files differ
diff --git a/Article-Image-Viewer/imageviewer.zip b/Article-Image-Viewer/imageviewer.zip
new file mode 100644
index 0000000..3af692f
--- /dev/null
+++ b/Article-Image-Viewer/imageviewer.zip
Binary files differ
diff --git a/Article-Internationalization/how2I18n.html b/Article-Internationalization/how2I18n.html
new file mode 100644
index 0000000..929e39f
--- /dev/null
+++ b/Article-Internationalization/how2I18n.html
@@ -0,0 +1,1255 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<META name="GENERATOR" content="IBM WebSphere Studio Homepage Builder V6.0.2 for Windows">
+<META http-equiv="Content-Style-Type" content="text/css">
+<title>How to Internationalize your Eclipse Plug-In</title>
+<link rel="stylesheet" href="../../default_style.css">
+</head>
+<BODY link="#0000ff" vlink="#800080" bgcolor="#ffffff" leftMargin="2" topMargin="2" marginwidth="2" marginheight="2">
+<div align="right">&nbsp; <font face="Times New Roman, Times, serif" size="2">Copyright
+ &copy; 2002 International Business Machines Corp.</font>
+ <table border=0 cellspacing=0 cellpadding=2 width="100%">
+ <tr>
+ <td align=LEFT valign=TOP colspan="2" bgcolor="#0080C0"><b><font face="Arial,Helvetica"><font color="#FFFFFF">&nbsp;Eclipse
+ Corner Article</font></font></b></td>
+ </tr>
+ </table>
+</div>
+<div align="left">
+ <h1><img src="images/Idea.jpg" height=86 width=120 align=CENTER></h1>
+</div>
+<p>&nbsp;</p>
+
+<h1 ALIGN="CENTER">How to Internationalize your Eclipse Plug-In</h1>
+<BLOCKQUOTE>
+<b>Summary</b>
+<br>
+This article is a roadmap for writing Eclipse plug-ins destined for the
+international market. We'll begin with a brief review of the motivations
+and technical challenges of internationalization, followed by step-by-step
+instructions of how to internationalize your Eclipse plug-in.
+<p><B>By Dan Kehn, Scott Fairbrother, and Cam-Thu Le</b><br>
+IBM Eclipse ISV Enablement
+(Jumpstart) Team
+
+ <p>August 23, 2002</p>
+ <p>Editor's note: This article reflects Eclipse release 2.0.</p>
+</blockquote>
+<H2>Introduction</H2>
+<p>An old joke in the internationalization community goes like this:</p>
+<blockquote>"A person who speaks three languages is called trilingual.
+ And a person who speaks two languages is called bilingual.
+ So what do you call someone who only speaks one language?"
+<P><I>&lt;insert dramatic pause here&gt;</I></P>
+</blockquote>
+<blockquote>
+ "American."
+</blockquote>
+<p>Today, providing a software product solely in English is no longer acceptable
+ from a usability, quality, marketing, and in some cases, legal standpoint. Enabling your product for the world market simply makes economic sense. And the enablement process is relatively straightforward, as this article will show.</p>
+<p>A few notes before we begin. Because the Eclipse
+Platform adopts the internationalization
+implementation provided with the Java SDK, it's helpful
+to read the <a href="http://java.sun.com/docs/books/tutorial/i18n/intro/index.html">Java
+ Tutorial: Internationalization</a> trail before continuing. The tutorial presents a fine overview of the issues and
+ steps involved in the process. We will assume that you've already read the tutorial
+ so we can underscore the key points, surface other noteworthy items, and cover
+ Eclipse-specific issues and steps in this article. And when you run into unfamiliar
+ terminology or acronyms in this article,
+jump to our <a href="#glossary">glossary</a>.</p>
+<H3><a name="overview">Overview of internationalization</a></H3>
+<p><i>Internationalization</i> is the process of creating software for the world market.
+ Besides the economic benefits, some countries require products to pass certain localization requirements set by the government before it can be introduced to their markets.</p>
+<p>The process of internationalition is usually accomplished in two steps:</p>
+<ol>
+<li>
+<b>NLS-enabling the product.</b>
+<br />
+ This step covers coding techniques and user interface
+ design issues. Enabling a product for National Language Support (NLS) ensures the product is designed for national language function
+ and uses proper APIs to handle national language data. During this step, smart
+ coding practices -- such as avoiding hardcoded strings, making input buffers
+ large enough to hold translatable text, properly parsing strings that contain
+ non-Latin characters, not localizing strings saved as part of a file format,
+ and isolating the national language elements from program code -- must be weighed
+ and considered so the translation can be completed with minimal expense and
+ effort.
+<p>
+ </li>
+<li>
+<b>Translating the product.</b>
+<br />This step involves translating the domestic
+language elements
+ into a foreign language. As with words and phrases, pictures
+ and symbols may also be interpreted differently
+by various cultures. It is during
+ the translation verification step that
+all translations are reviewed for contextual
+ accuracy, icons or clip art are modified
+to ensure there are no user misinterpretations,
+ and page layouts are checked for inadvertent
+text truncation. While verifying
+ the product's functional integrity after
+translation, this step also looks for
+ hidden cultural impacts.
+</li>
+</ol>
+<H3><a name="affected">What does internationalization affect?</a></H3>
+<p><i>Monoglots take note</i>: This is the beginning of your sensitivity training.
+ There may be a quiz at end of this article. :-)</p>
+<p>Let's begin with a distillation of the list of culturally dependent data
+presented in the Java Internationalization tutorial, reordered by the likelihood
+that the typical developer will encounter it, and followed by details on
+each:</p>
+<ol>
+<li>
+<a href="#data_text">Text</a>
+<br />Messages, labels on GUI components
+ <br />Online help (*.html), Plug-in manifest (plugin.xml)<br />
+ </li>
+<li>
+<a href="#data_formatting">Data formatting</a>
+<br />Numbers, dates, times, currencies
+ <br />Phone numbers, postal addresses<br />
+ </li>
+<li>
+<a href="#data_regional">Regional and personal substitutions</a>
+<br />Measurements
+ <br />Honorifics and personal titles<br />
+ </li>
+<li>
+<a href="#data_multimedia">Multimedia considerations</a>
+</li>
+</ol>
+<H4><a name="data_text">Text</a></H4>
+<p><b>Messages, labels on GUI components</b>
+<br />
+Resource bundles nicely handle language-dependent
+texts. The strategy is either to load all
+strings at once into a <a href="http://java.sun.com/j2se/1.3/docs/api/java/util/class-use/ResourceBundle.html">ResourceBundle</a> subclass, or to retrieve them individually.
+The Eclipse Java Development Tooling (JDT)
+in version 2.0 provides wizards to support
+the detection of translatable strings. We'll
+return to them shortly in <a href="#steps">Internationalization steps</a>.</p>
+<p>Loading translated strings into memory is only the first step. The next
+step is to pass them to the appropriate controls for display (such as a
+label, text field, menu choice, etc.). The page designer and programmer
+must work together to assure that the chosen layout allows for appropriate
+resizing and reflowing of the dialog. The layout support in the Standard
+Widget Toolkit (SWT) library relies heavily on the programmer to &quot;do
+the right thing&quot; by specifying layout descriptions that react appropriately
+to changes in field sizes. The article <A href="http://eclipse.org/articles/Understanding%20Layouts/Understanding%20Layouts.htm">Understanding Layout in SWT</A> covers the implementation issues in detail.</p>
+<p>This is particularly important because text
+length increases during translation. English
+phrases are often shorter than their equivalent
+translations, usually on the order of 40%.
+Font sizes also may need to be modified to
+accommodate the local language.
+</p>
+<p>
+<b>
+<a name="plugin_xml_attribs">Online help (*.html), Plug-in manifest (plugin.xml)</a>
+</b>
+<br />
+ These forms of text content are more involved than simple key/value-oriented
+ properties files, so the steps to their externalization are slightly more complex.</p>
+<p>In the case of the manifest file, it is coupled
+with a similarly named property file, plugin.properties,
+ containing only the externalized text.
+Special care must be taken with manifest
+files like plugin.xml and fragment.xml, since
+the attributes of the tags can contain both
+translated and untranslated text. Consider
+the benign example below:</p>
+<a name="c1"><b>Listing 1. Plug-in manifest file, before translation</b></a><table border="1" cellspacing="0" cellpadding="5" width="100%" bgcolor="#CCCCCC">
+<tr><td><pre><code> &lt;plugin
+ name=&quot;Jumpstart Example Plug-in&quot;
+ id=&quot;com.ibm.jumpstart.example&quot;
+ version=&quot;2.0.0&quot;
+ provider-name=&quot;IBM Corporation&quot;
+ class=&quot;com.ibm.jumpstart.example.ExamplePlugin&quot;&gt;
+</code></pre></td></tr>
+</table>
+<p>Here we see a mix of translatable text, untranslatable text, and "gray
+ area" translatable text, all as tag attributes. Clearly the
+<code>id</code> and <code>class</code> attributes are not translatable,
+since they represent programming identifiers. It is equally certain that the
+<code>name</code> attribute should be translated.</p>
+<p>You might be tempted to consider the
+<code>version</code> attribute (because of the locale-dependent decimal separator) or <CODE>provider-name</CODE> attribute (because of the locale-dependent legal attribution &quot;Corporation&quot;)
+as candidates for translation, since they will be displayed to the end
+user. However, version numbers are generally left untranslated for two
+reasons: end users attribute little meaning to their numeric value, and
+programmers sometimes write code that expects version numbers to be a composed
+string like &quot;3.5.4&quot;. It is arguably a better design decision
+that the version information be stored as separate numbers like major,
+minor, and service update to avoid the need to parse a version string,
+but that discussion is beyond the scope of this article.</p>
+<p>The <CODE>provider-name</CODE> may be left untranslated as well, since &quot;Corporation&quot; has legal meaning that can defy accurate translation. After identifying what text needs to be externalized, our example now looks like this:</p>
+<a name="c2"><b>Listing 2. Plug-in manifest file, after translation</b></a><table border="1" cellspacing="0" cellpadding="5" width="100%" bgcolor="#CCCCCC">
+<tr><td><pre><code> &lt;plugin
+ name=&quot;<B>%<span class="boldcode">plugin.name</span></B>&quot;
+ id=&quot;com.ibm.jumpstart.example&quot;
+ version=&quot;2.0.0&quot;
+ provider-name=&quot;IBM Corporation&quot;
+ class=&quot;com.ibm.jumpstart.example.ExamplePlugin&quot;&gt;
+</code></pre></td></tr>
+</table>
+<p>where <code>plugin.properties</code> contains the externalized string, &quot;Jumpstart
+ Example Plug-in&quot; associated with the key <code>plugin.name</code>.</p>
+<p>This simple example demonstrates
+that translating isn't simply providing equivalent
+words or phrases for your text; it also involves
+an understanding of the local cultural considerations
+and potential legal impacts. This is why
+a translation professional is necessary,
+as well as translation verification testing.</p>
+<H4><a name="data_formatting">Data formatting</a></H4>
+<p><b>Numbers, dates, times, currencies</b>
+<br />
+The Java library includes classes that handle the necessary formatting for numbers
+ (decimal separator, thousands separator, grouping), dates (MDY, DMY, first day
+ of work week), times (12- or 24-hour format, separator), and currencies (local
+ symbol, shown as suffix or prefix, leading separator or none).</p>
+<p>
+<b>Phone numbers, postal addresses</b>
+<br />
+These are more subtle and less common text
+translation concerns, but still noteworthy.
+Many applications simply allow free-format
+entry of phone numbers since there are so
+many local variations. Postal addresses are
+straightforward: Adding a "State/Province"
+field and allowing for multiple address lines
+is generally sufficient.</p>
+<H4><a name="data_regional">Regional and personal substitutions</a></H4>
+<p><b>Honorifics and personal titles</b>
+<br />
+Though less common in the United States, the proper enablement
+ of honorifics (Mr., Mrs., Dr.) is considered absolutely necessary elsewhere to avoid a
+ serious breach of etiquette.</p>
+<p>
+<b>Measurements</b>
+<br />
+These are less frequently encountered. This
+involves substitution of measurement indications
+with corresponding conversion (for example, miles
+versus kilometers). In many cases, users
+will need either simultaneous display of
+a measure in different units, or an easy
+way of toggling between them.</p>
+<H4><a name="data_multimedia">Multimedia considerations</a></H4>
+<p>In general, products should select regionally
+ neutral sounds, colors, graphics, and icons.</p>
+<p>This means no Homer Simpson "D'oh!" sound associated with
+error messages. If you're thinking that
+no serious development organization would
+do such a thing, consider an icon that is
+typical of those that are proposed and rejected:</p>
+<p>
+<IMG src="images/route66.jpg" width="39" height="39" alt="Route 66 icon" />
+</p>
+<p>The developer wanted to convey a metaphor for &quot;IP router&quot; by using a symbol harkening back to a national highway that traversed the United States from Chicago to Los Angeles, called <A href="http://www.national66.org/66hstry.html">Route 66</A>. Most Americans would find this metaphor obtuse; imagine the confusion of the hapless non-US user.</p>
+<p>Similarly, the image below may be intuitive to many North American users:
+<p>
+<IMG src="images/mailbox.jpg" width="85" height="95" alt="Mailbox icon" />
+</p>
+ <p>But in recognition studies, others from outside
+the United States have guessed that this
+is a birdhouse. This is the more
+universally accepted image for mail:</p>
+<p>
+<IMG src="images/envelope.jpg" width="23" height="23" alt="Envelope icon" />
+</p>
+<p>To avoid confusing and potentially offensive visuals, the best course is to engage professional graphic artists who are aware of cultural issues.</p>
+<H3><a name="steps">Internationalization steps</a></H3>
+<p>Now let's turn to the actual steps for internationalizing your Eclipse plug-in:</p>
+<ol>
+<li>
+<a href="#step1">Move translatable strings into *.properties
+ files</a>
+</li>
+<li>
+<a href="#step2">Separate presentation-dependent parameters</a>
+</li>
+<li>
+<a href="#step3">Use proper locale-sensitive data formatting,
+ substitutions APIs</a>
+</li>
+<li>
+<a href="#step4">Test in domestic language</a>
+</li>
+<li>
+<a href="#step5">Create initial translated plug-in fragment</a>
+</li>
+<li>
+<a href="#step6">Prepare and send domestic language materials
+ for translation</a>
+</li>
+<li>
+<a href="#step7">Repackage and validate translated materials</a>
+</li>
+<li>
+<a href="#step8">Deploy fragments</a>
+</li>
+</ol>
+<p>We'll discuss each of these steps in detail.</p>
+<H4><a name="step1">Step 1. Move translatable strings into *.properties
+files</a></H4>
+<p>Fortunately, Eclipse's Java Development Tooling provides considerable help to properly separate translatable strings. The <b>Source &gt; Find Strings to Externalize</b> menu choice displays the <b>Externalize Strings</b> wizard. This wizard will lead you through
+the steps to locate hardcoded strings in
+your code, classify them as translatable
+or not, then modify the code to use a resource
+bundle where appropriate.</p>
+<p>We'll introduce the <b>Externalize Strings</b> wizard with an example,
+ the canonical "Hello World" <i>before</i> using the wizard:</p>
+<a name="c3"><b>Listing 3. Hello world, before translation</b></a><table border="1" cellspacing="0" cellpadding="5" width="100%" bgcolor="#CCCCCC">
+<tr><td><pre><code> package com.jumpstart.nls.example.helloworld;
+ public class HelloWorld {
+ static public void main(String[] args) {
+ System.out.println(&quot;Copyright (c) IBM Corp. 2002.&quot;);
+ System.out.println(&quot;Hello.&quot;);
+ System.out.println(&quot;How are you?&quot;);
+ System.out.println(&quot;Goodbye.&quot;);
+ }
+}
+</code></pre></td></tr>
+</table>
+<p>Selecting <CODE>HelloWorld.java</CODE> and then <b>Source &gt; Externalize Strings</b> will display the wizard shown in Figure 1:</p>
+<p>
+<a name="f2"><b>Figure 1. Externalize Strings wizard</b></a><br /><IMG src="images/image2.jpg" width="576" height="430" alt="Externalize Strings wizard" />
+</p>
+<p>By selecting an entry from the table and
+then one of the pushbuttons to the
+ right, you can mark the strings as belonging
+to one of three cases:</p>
+<ul>
+<li>
+<IMG src="images/translate.jpg" width="10" height="10" alt="Translate" />
+ Translate
+<br />
+Action: An entry is added in the properties files; the auto-generated key and
+ access code is substituted in the code for the original string. The string used
+ to specify the key is marked as non-translatable with a comment marker, such as
+"<code>// $NON-NLS-1$</code>"<br />
+<br />
+</li>
+<li>
+<IMG src="images/never.jpg" width="12" height="11" alt="Never translate" />
+ Never Translate<br />
+Action: The string is marked as non-translatable with a comment marker. The
+ <b>Externalize Strings</b> wizard will not flag it as untranslated in subsequent
+ executions.<br />
+<br />
+</li>
+<li>
+<IMG src="images/skip.jpg" width="11" height="11" alt="Skip" />
+Skip<br />
+Action: Nothing is modified. Subsequent executions of the <b>Externalize Strings</b> wizard will flag the string as potentially translatable.</li>
+</ul>
+The trailing number in the <code>// $NON-NLS-1$</code> comment marker indicates which
+ string is not to be translated in the case where are there are several strings
+ on a single line. For example:
+ <blockquote>
+<code>x.foo("Date", "TOD", "Time"); // $NON-NLS-2$</code>
+</blockquote>
+ <p>Here the middle parameter is flagged as non-NLS. The other two are skipped.</p>
+<p>Returning to our example, note that the total number of strings for each category
+ is summarized below the list. The key names of the externalized strings are
+ auto-generated based on the string value, but they can be renamed directly in
+ the table. In addition, an optional prefix can be specified (<code>S_</code>
+ in the example below).</p>
+<p>
+<a name="f6"><b>Figure 2. Externalize Strings wizard</b></a><br /><IMG src="images/image6.jpg" width="576" height="434" alt="Externalize Strings wizard" />
+</p>
+<p>
+<i>Hint</i>: Clicking the icon in the first column of a given row will advance
+ to the next choice: Translate, Never Translate, or Skip.</p>
+<p>Now that we've identified what strings are translatable, continue to the next
+ step to choose how they will be externalized. Here's the page displayed after
+ selecting <b>Next</b>; the <b>Property file name</b> and resource bundle accessor
+ <b>Class name</b> were modified to more specific values than the defaults:</p>
+<p>
+<a name="f7"><b>Figure 3. Externalize Strings wizard</b></a><br /><IMG src="images/image7.jpg" width="576" height="434" alt="Externalize Strings wizard" />
+</p>
+<p>The resource bundle accessor class will contain code to load the properties
+ file and a static method to fetch strings from the file. The wizard will generate
+ this class, or you can specify your own existing alternative implementation.
+ In the latter case, you may want to uncheck the <b>Use default substitution
+ choice</b> and specify an alternative code pattern for retrieving externalized
+ strings. If the accessor class is outside of the package (for example, a centralized
+ resource bundle accessor class), you can optionally specify that you want to
+ <b>Add [an] import declaration</b> to the underlying source.</p>
+<p>The <b>Externalize Strings</b> wizard uses the JDT Refactoring framework, so
+ the next two pages should look familiar. First, a list of warnings:</p>
+<p>
+<a name="f8"><b>Figure 4. Externalize Strings wizard</b></a><br /><IMG src="images/image8.jpg" width="576" height="357" alt="Externalize Strings wizard" />
+</p>
+<p>And finally a side-by-side presentation of the proposed changes:</p>
+<p>
+<a name="f9"><b>Figure 5. Externalize Strings wizard</b></a><br /><IMG src="images/image9.jpg" width="576" height="356" alt="Externalize Strings wizard" />
+</p>
+<p>Once you select <b>Finish</b>, the wizard performs the source code modifications,
+ creates the resource bundle accessor class, and generates the initial properties
+ file. Here is the code for the standard resource bundle accessor class:</p>
+<a name="c4"><b>Listing 4. Standard resource bundle accessor class</b></a><table border="1" cellspacing="0" cellpadding="5" width="100%" bgcolor="#CCCCCC">
+<tr><td><pre><code> package com.jumpstart.nls.example.helloworld;
+ import java.util.MissingResourceException;
+ import java.util.ResourceBundle;
+
+ public class HelloWorldMessages {
+
+ private static final String BUNDLE_NAME =
+ &quot;com.jumpstart.nls.example.helloworld.HelloWorld&quot;; //$NON-NLS-1$
+
+ private static final ResourceBundle RESOURCE_BUNDLE =
+ ResourceBundle.getBundle(BUNDLE_NAME);
+
+ private HelloWorldMessages() {}
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return &quot;!&quot; + key + &quot;!&quot;;
+ }
+ }
+ }
+</code></pre></td></tr>
+</table>
+<p>The only variation in this generated code
+is the value assigned to the static final,
+<code>BUNDLE_NAME</code>. Before we continue to the next
+step, below are some noteworthy guidelines
+contributed by Erich Gamma and Thomas M&#228;der
+of the JDT team.</p>
+<H4><a name="gln">Guidelines for managing resource bundles and properties files</a></H4>
+<p>These guidelines are designed to:</p>
+<ul>
+<li>Reduce the number of NLS errors, in other words, the values of externalized strings
+ that are not found at runtime</li>
+<li>Enable cross-referencing between the keys
+ referenced in the code and the keys defined
+ in the properties file</li>
+<li>Simplify the management of the externalized strings. Using a centralized
+ property file can result in frequent change conflicts. In addition, it requires
+ the use of prefixes to make keys unique and complicates the management of
+ the keys.</li>
+</ul>
+<p>To achieve these goals, we propose the following guidelines: </p>
+<ol>
+<li>
+<b>Use a properties file per package, and qualify
+the keys by class name</b>
+<p>For example, all the strings for the JDT
+search component are in SearchMessages.properties,
+with key/value pairs like:<br />
+<br />
+<code>SearchPage.expression.pattern=(? = any character, * = any string) <BR>
+ ShowTypeHierarchyAction.selectionDialog.title=Show in Type Hierarchy </code>
+</p>
+</li>
+<li>
+<b>Use a dedicated static resource bundle accessor
+class </b>
+<p>Let the <b>Externalize Strings</b> wizard generate this class. It should be
+named like the properties file. So in our
+example, it would be called SearchMessages.
+When you need to create formatted strings,
+add the convenience methods to the bundle
+accessor class. For example:</p>
+<a name="c5"><b>Listing 5. Static resource bundle accessor class</b></a><table border="1" cellspacing="0" cellpadding="5" width="100%" bgcolor="#CCCCCC">
+<tr><td><pre><code> public static String getFormattedString(String key, Object arg) {
+ String format= null;
+ try {
+ format= RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return &quot;!&quot; + key + &quot;!&quot;;//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ if (arg == null)
+ arg= &quot;&quot;; //$NON-NLS-1$
+ return MessageFormat.format(format, new Object[] { arg });
+ }
+ public static String getFormattedString (String key, String[] args) {
+ return MessageFormat.format(RESOURCE_BUNDLE.getString(key), args);
+ }
+</code></pre></td></tr>
+</table>
+<br />
+</li>
+<li>
+<b>Do not use computed keys</b>
+<p>There is no easy way to correlate a computed
+key in the code with the key in the properties file. In particular
+it is almost impossible to determine whether a key is no longer in use.</p>
+</li>
+<li>
+<b>The convention for the key name is &lt;classname&gt;.&lt;qualifier&gt;</b>
+<p>Example: PackageExplorerPart.title</p>
+</li>
+</ol>
+<H4><a name="step2">Step 2. Separate presentation-dependent parameters</a></H4>
+<p>Not all externalized text is simply words and phrases that will be translated to a target language. Some are more specifically related to your plug-in's implementation. Examples include properties, preferences, and default dialog settings.</p>
+<p>Here are a few specific examples that might
+find their way into a properties file:</p>
+<ul>
+<li>Size or layout constraints. For example,
+ the appropriate width of a non-resizable
+ table column</li>
+ <li>Default fonts that are dependent on the language or operating system. A good
+ default font for Latin-1 languages is an invalid choice for DBCS languages.</li>
+</ul>
+<p>For those plug-ins that subclass from <a href="http://eclipse.org/documentation/html/plugins/org.eclipse.platform.doc.isv/doc/reference/api/org/eclipse/ui/plugin/AbstractUIPlugin.html">AbstractUIPlugin</a>, NL-related parameters can also be found
+in its <a href="http://eclipse.org/documentation/html/plugins/org.eclipse.platform.doc.isv/doc/guide/preferences_prefs.htm">default
+ preference</a> stores (pref_store.ini) and <a href="http://eclipse.org/documentation/html/plugins/org.eclipse.platform.doc.isv/doc/guide/dialogs_settings.htm">dialog
+ settings </a>(dialog_settings.xml). The Eclipse Workbench itself does not use
+ default preference stores, opting instead to store defaults in properties files
+ and then initialize them via AbstractUIPlugin's <code>initializeDefaultPreferences(IPreferenceStore)</code> method.</p>
+<H4><a name="step3">Step 3. Use proper locale-sensitive data formatting, substitutions APIs</a></H4>
+<p>Please refer to the detailed coverage in the <a href="http://java.sun.com/docs/books/tutorial/i18n/intro/index.html">Java Tutorial: Internationalization</a> trail.</p>
+<H4><a name="step4">Step 4. Test in domestic language</a></H4>
+<p>Testing the readiness of a product for translation is non-trivial and beyond
+the scope of this article. However, the follow-on article <a href="http://eclipse.org/articles/Article-TVT/how2TestI18n.html">How to Test your Internationalized Eclipse Plug-in</a> presents strategies for validating the NL-sensitive aspects of your product.</p>
+<H4><a name="step5">Step 5. Create initial translated plug-in fragment</a></H4>
+<p>At this point, we could simply copy our domestic language property files to
+similarly named files with locale-specific suffixes (for example, MyMessages_xx.properties,
+where xx is the language), and move to step 6, <a href="#step6">Prepare and send domestic language materials for translation</a>. In this case, the product is delivered with its code and whatever languages it supports as a single install.</p>
+<p>However, this approach has a few drawbacks.
+Firstly, the code and its national language
+resources are intermingled in the same directory
+/ JAR file. If the translation lags the code
+delivery, the plug-in JAR file must be updated,
+despite the fact that the underlying code
+is unchanged. Secondly, files other than
+property files are not inherently locale-sensitive,
+so they must be segregated to separate directories
+for each language (for example, HTML, XML, images).</p>
+<p>To address these issues, the Eclipse Platform
+introduces the notion of another reusable
+component that complements plug-ins, called
+a <i>plug-in fragment</i>. A plug-in fragment provides
+additional functionality to its target plug-in.
+At runtime, these plug-in contributions
+are merged along with all dependent fragments.
+These contributions can include code contributions
+and contributions of resources associated
+with a plug-in, like property and HTML files.
+In other words, the plug-in has access to
+the fragment's contents via the plug-in's classloader.</p>
+<H4><a name="g1">How and why to use fragments to provide the translatable information</a></H4>
+<p>A plug-in fragment is an ideal way to distribute
+Eclipse-translated information including
+HTML, XML, INI, and bitmap files. Delivering
+translations in a non-intrusive way, the
+Eclipse Platform translations are packaged
+in fragment JAR files and are added to existing
+Eclipse installations without changing or
+modifying any of the original runtime elements.
+This leads to the notion of a <i>language
+pack</i>.</p>
+<p>The Eclipse Platform merges plug-in fragments
+in a way that the runtime elements in the
+fragment augment the original targeted plug-in.
+The target plug-in is not moved, removed,
+or modified in any way. Since the fragment's
+resources are located by the classloader, the plug-in developer
+has no need to know whether resources are
+loaded from the plug-in's JAR file or
+one of its fragments' JAR files.</p>
+<H4><a name="g2">Eclipse Language Pack JAR</a></H4>
+<p>The Java language supports the notion of a language pack
+with the resource bundle facility. The Java
+resource bundles do not require modification
+of the application code to support another
+language. The *.properties file namespace
+avoids collisions through the following naming
+convention: <i>basename_lang_region_variant</i>. At runtime, the <a href="http://java.sun.com/j2se/1.3/docs/api/java/util/class-use/ResourceBundle.html">ResourceBundle</a> facility finds the appropriate properties
+file for the current locale.</p>
+<p>The approach to deploying files such as HTML
+and XML files in fragments is slightly different
+than Java resource bundles in that the Eclipse
+fragment uses a directory structure to sort
+out the different language versions.</p>
+<p>
+<b>Example fragment contents</b>
+<br />
+The plug-ins and the plug-in fragments reside
+in separate subdirectories found immediately
+under the eclipse subdirectory. Looking at
+our example fragment, as deployed on a German
+system, we see an \nl folder, fragment.xml
+and an nl1.jar file.</p>
+<p>
+<a name="f20"><b>Figure 6. Fragments subdirectories</b></a><br /><IMG src="images/image20.jpg" width="504" height="278" border="0" alt="" />
+</p>
+<p>Typically, translated *.properties files
+are suffixed according to the resource bundle
+rules and deployed in JAR files. In contrast,
+when a view needs an input file type whose
+name is not locale-sensitive like resource
+bundles (such as *.xml), we define a subdirectory
+structure for each language version of the
+file. The de subdirectory above
+is one such example, where de = German.</p>
+<p>
+<b>Fragment manifest</b>
+<br />
+Each plug-in folder can optionally contain a fragment
+manifest file, fragment.xml. The manifest
+file describes the plug-in fragment, and
+is almost identical to the plug-in manifest
+(plugin.xml), with the following two exceptions:</p>
+<ul>
+<li>The <code>class</code> attribute is gone since
+ fragments do not have a plug-in class. They
+ just follow their target's specification.</li>
+<li>There are no dependencies because the fragments have the same dependencies
+ as their target plug-in.</li>
+</ul>
+<p>Manifests used to describe a national language
+fragment are typically quite simple, specifying
+only the <code>&lt;fragment&gt;</code> and <code>&lt;runtime&gt;/&lt;library&gt;</code> tags. Here's the example
+fragment manifest file in its entirety:</p>
+<a name="c6"><b>Listing 6. Fragment manifest file</b></a><table border="1" cellspacing="0" cellpadding="5" width="100%" bgcolor="#CCCCCC">
+<tr><td><pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;fragment
+ id=&quot;com.jumpstart.nls.example.helloworld.nl1&quot;
+ name=&quot;NLS Example Plugin NL Support&quot;
+ version=&quot;1.0.0&quot;
+ provider-name=&quot;IBM&quot;
+ plugin-id=&quot;com.jumpstart.nls.example&quot;
+ plugin-version=&quot;1.0.0&quot;&gt;
+&lt;runtime&gt;
+ &lt;library name=&quot;nl1.jar&quot; type=&quot;resource&quot;/&gt;
+ &lt;library name=&quot;$nl$/&quot;/&gt;
+&lt;/runtime&gt;
+&lt;/fragment&gt;
+</code></pre></td></tr>
+</table>
+<p>The <code>&lt;fragment&gt;</code> tag attributes are:</p>
+<ul>
+<li>
+<b>
+<code>name</code>
+</b> -- User-displayable name for the extension.</li>
+<li>
+<b>
+<code>id</code>
+</b> -- Identifier for this fragment configuration.
+Used to uniquely identify this fragment instance.</li>
+<li>
+<b>
+<code>plugin-id</code>
+</b> -- Reference to the target extension point. This plug-in fragment merges with this target extension.</li>
+<li>
+<b>
+<code>plugin-version</code>
+</b> -- Version of the fragment plug-in. </li>
+<li>
+<b>
+<code>version</code>
+</b> -- Version specification in major.minor.service
+format.</li>
+ <li><B><CODE>type</CODE></B> -- The default is '&quot;code&quot;. Specifying &quot;resource&quot; indicates the library includes resource files and no code. This improves overall performance significantly because resource-only libraries are skipped when loading code.</li>
+ </ul>
+<p>The <code>&lt;runtime&gt;</code> section contains a definition of one or more libraries that make up the
+plug-in fragment runtime. The referenced libraries are used by the platform
+execution mechanisms where the plug-in loads, merges, and executes the
+correct code required by the plug-in. The <CODE>name</CODE> attribute accepts a library name (&quot;nl1.jar&quot; above) or directory
+containing resources. A directory reference must contain a trailing path
+separator. Optionally, the specification may include a substitution variable.
+In the example above, the second library includes a variable substitution
+<CODE>$nl$</CODE> based on the locale; it is used above to add a language/region specific
+folder to the library search path (e.g., a locale of &quot;it&quot; = Italy,
+&quot;fr&quot; = France, or &quot;de&quot; = Germany, etc. would add the
+corresponding plug-in subdirectory <CODE>it/</CODE>, <CODE>fr/</CODE>, or <CODE>de/</CODE> to the list of searched paths). The value of the <CODE>nl</CODE>, <CODE>os</CODE>, <CODE>ws</CODE>, and <CODE>arch</CODE> substitutions variables can be displayed and modified on the <B>Window &gt; Preferences &gt; Plug-in Development &gt; Target Environment</B> page. The <CODE>nl</CODE> substitution variable is used in those cases where it is not possible or practical to suffix files with the locale name.</p>
+<p>
+<b>Building a fragment</b>
+<br />
+The Eclipse Workbench comes with a tool used
+in plug-in development: <i>the Plug-in Development Environment
+(PDE)</i>. The PDE contains support for developing
+plug-in fragments.</p>
+<p>Let's now examine how to build a fragment
+for national language translations using
+the PDE. There is no practical limit to the
+number of languages in a given fragment.
+The fragment then is the basis of our "Language
+Pack" containing one or more language
+translations. However, in this example, we'll
+confine our language pack to the German translation.</p>
+<p>To build a plug-in fragment, start the New
+Project wizard (<b>File</b> &gt; <b>New</b> &gt; <b>Project...</b>), select the <b>Plug-in Development</b> category, then <b>Fragment Project</b> type. On the first page of the New Fragment
+Wizard, type the project name. Keep in mind
+that the project name will also become the
+fragment ID. For example, starting a project
+adding national language support to the HelloWorld
+example, we would name our project "com.jumpstart.nls.example.helloworld.nl1".
+The trailing ".nl1" is not required,
+but does help distinguish fragments that
+represent "language packs" from
+fragments that add additional code and functionality.</p>
+<p>
+<a name="f7"><b>Figure 7. Starting a fragment project</b></a><br /><IMG src="images/fraggen1.jpg" border="0" width="500" height="500" alt="Starting a fragment project" />
+</p>
+<p>Press <b>Next</b>. We see the default values for the project's
+source folder and runtime library on the
+second page:</p>
+<p>
+<a name="f8"><b>Figure 8. Defining fragment folders</b></a><br /><IMG src="images/fraggen2.jpg" border="0" width="500" height="500" alt="Defining fragment folders" />
+</p>
+<p>These values seem reasonable, so pressing
+<b>Next</b> again, we arrive at the "Fragment Code
+Generators" page. Select the second
+radio button to indicate we want to create
+the fragment manifest file from a template,
+then select the <b>Default Fragment Generator</b> wizard from the list.</p>
+<p>
+<a name="f9"><b>Figure 9. Selecting the default wizard</b></a><br /><IMG src="images/fraggen3.jpg" border="0" width="500" height="500" alt="Selecting the default wizard" />
+</p>
+<p>After pressing <b>Next</b>, we see the "Simple Fragment Content"
+page. This page has two entries used to target
+our fragment on an existing plug-in. We must
+supply the plug-in target id and version.
+We can use the <b>Browse</b> button to select the plug-in that we want
+to extend.</p>
+<p>
+<a name="f10"><b>Figure 10. Targeting the fragment</b></a><br /><IMG src="images/image23.jpg" border="0" width="500" height="500" alt="Targeting the fragment" />
+</p>
+<p>Now let's proceed to the fragment manifest editor, which is similar to the plug-in manifest editor in that
+it is a multi-page editor with Overview,
+Runtime, Extensions, Extension Points, and
+Source pages.</p>
+<p>
+<a name="f11"><b>Figure 11. Fragment manifest editor</b></a><br /><IMG src="images/image24.jpg" border="0" width="518" height="492" alt="Fragment manifest editor" />
+</p>
+<p>Notice the tabbed pages corresponding to
+sections of the fragment xml file. We will
+be using the <b>Runtime</b> page to point the fragment
+classpath at the libraries containing our
+translations.</p>
+<p>We specified the nl1.jar in the new fragment wizard so that library is already
+ included in the classpath of this fragment. What is missing at this point is
+ the inclusion of the locale-specific folder. You can add new runtime libraries
+ by selecting <b>More</b> from the Runtime Libraries section of the Overview
+ page, or by turning to the Runtime page, selecting <b>New...</b>, then entering
+ $nl$/.</p>
+<p>
+<a name="f12"><b>Figure 12. Fragment runtime information</b></a><br /><IMG src="images/image25.jpg" border="0" width="502" height="317" alt="Fragment runtime information" />
+</p>
+<p>Taking a look at the Source page of the fragment
+manifest editor, we see that the PDE generates
+all the XML necessary to describe our plug-in
+fragment.</p>
+<p>
+<a name="f13"><b>Figure 13. Fragment source</b></a><br /><IMG src="images/image26.jpg" border="0" width="444" height="374" alt="Fragment source" />
+</p>
+<H4><a name="step6">Step 6. Prepare and send domestic language materials for translation</a></H4>
+<p><br />
+Producing correct translations requires specific skills, which you must purchase. (Unfortunately, your four years
+of high school German classes do not qualify you!) There are many
+companies that will gladly produce professional-quality translations.</p>
+<p>For the Eclipse Platform, this step was accomplished
+in two phases. The first phase involved sending
+all the externalized text to a translation
+center. This first-pass translation is done
+"out of context." The translator
+does not see the running product, nor do
+they have product-specific experience. They
+have tools at their disposal to help speed
+the translations and assure consistency,
+but ultimately they rely on translation testers
+to validate the running product in the target
+language (the second phase).</p>
+<p>The risk and consequences of performing an
+out-of-context translation, the results of
+which are sometimes quite amusing, are
+discussed in the follow-on article <a href="http://eclipse.org/articles/Article-TVT/how2TestI18n.html">How To Test your Internationalized Eclipse Plug-in</a>.</p>
+<H4><a name="step7">Step 7. Repackage and validate translated materials</a></H4>
+<p>Now having the translated files, we reassemble
+them in their appropriate directories/JAR
+files as described in step 5, <a href="#step5">Create initial translated plug-in fragment</a>. The NL1 Fragment folder contains
+language versions of the plugin.properties
+file. After translating the HelloWorld.properties
+file to German, we rename it to HelloWorld_de.properties
+and store it in the NL1 Fragment
+source folder. Note that the nl\de (German)
+folder is new and is created manually, not
+by the PDE. These language-specific folders
+segregate the versions of non-properties
+files (such as hello.xml shown
+below) as we add translations over time.</p>
+<p>
+<a name="f14"><b>Figure 14. Reassembled fragment project</b></a><br /><IMG src="images/nav3.jpg" border="0" width="326" height="323" alt="Reassembled fragment project" />
+</p>
+<p>Be aware that the translated properties files will very likely contain accented
+ characters that are codepage dependent, so properties files must be converted
+ to the ISO 8859-1 codepage expected by the <a href="http://java.sun.com/j2se/1.3/docs/api/java/util/PropertyResourceBundle.html">PropertyResourceBundle</a>
+ class. The native2ascii utility will handle codepage conversions and insert
+ any necessary Unicode escapes.</p>
+<p>The term <i>Unicode escape</i> deserves a bit more explanation.
+The native2ascii conversion utility, included
+with the Java SDK, accepts a source encoding
+and produces output encoded in ISO 8859-1,
+plus it transforms characters outside this
+codepage to the notation known as Unicode
+escapes. This notation is \udddd, where dddd
+= the codepoint of the desired character
+in the Unicode codepage.</p>
+<p>Here's an example. Consider
+the French phrase "Son p&#232;re est
+all&#233;&nbsp;&#224; l'h&#244;tel"
+(his father went to the hotel). This contains
+four accented characters that
+are not part of the Latin-1 codepage. Transforming
+this phrase with the native2ascii utility
+yields:
+<br />
+<br />
+<code>Son p\u00e8re est all\u00e9 \u00e0 h\u00f4tel</code>
+</p>
+<p>There are no longer any accented characters, and the resulting string is
+composed entirely of characters having codepoints that are found in ISO
+8859-1. But what are the <code>\u00e8</code>,
+<code>\u00e9</code>, <code>\u00e0</code>, and <code>\u00f4</code> that were substituted?
+They are the Unicode codepoints of the accented
+characters in \udddd notation.</p>
+<p>A little caveat when using the native2ascii utility:
+It assumes that the source encoding is the
+same as the active codepage of the machine
+that executes it. However, translators typically
+save the translations in their default country
+codepage, and this codepage is different
+in each country and each operating system.
+So the person responsible for integrating
+the translations will need to either (a)
+know in which codepage that the translators
+save their files, or (b) ask that they save
+it in a common codepage. You can specify
+the source encoding when invoking native2ascii
+with the<code>-encoding</code> parameter.</p>
+<p> <i>Tip:</i> If you are uncertain of the source codepage, you can spot-check
+ the output of native2ascii against <a href="#unicode_table">Unicode codepoints
+ of common accented Latin characters</a> table later in this article. If you
+ find \udddd notations in your converted files that are not in this table (such
+ as \u0205), it is likely that you specified the incorrect source encoding. There
+ is no equivalent spotcheck for DBCS languages, where practically all the characters
+ in the converted files are Unicode escapes. You simply have to be careful and
+ validate against the running product.</p>
+<p>Testing the translation merits its own article. The follow-on article <a href="http://eclipse.org/articles/Article-TVT/how2TestI18n.html">How to Test your Internationalized Eclipse Plug-in</a> describes the process and lessons learned during the recent translation verification of the Eclipse Platform, and includes a view (an Eclipse plug-in, of course!) for performing a quick check of property file translations.</p>
+<H4><a name="step8">Step 8. Deploy fragments</a></H4>
+<p>Fragment sources, similar to plug-in sources,
+may be packaged in a JAR file. Using the
+PDE to generate the JAR package, select the
+"fragment.xml" file and choose
+"<b>Create Fragment JARs...</b>&quot; from the pop-up menu. A wizard will guide you in creating a build script to produce all the required JARs for your fragment. If your <CODE>fragment.xml</CODE> file includes translatable strings, separate them into a <CODE>plugin.properties</CODE> file (just as you would for a plugin.xml file, i.e., there is no such thing as a &quot;fragment.properties&quot; file). This works because fragments are an extension of a plug-in and therefore inherits it dependencies, including its <CODE>plugin.properties</CODE> file values.</p>
+<p>
+<a name="f15"><b>Figure 15. Selecting the fragment.xml file</b></a><br /><IMG src="images/image28.jpg" border="0" width="320" height="241" alt="Selecting the fragment.xml file" />
+</p>
+<p>To deploy this example fragment, copy the fragment.xml, the \nl directory,
+and JAR to the com.jumpstart.example.helloworld.nl1 subdirectory in the
+plugins directory. This completes our example and the steps for internationalization.</p>
+<H3><a name="summary">Summary</a></H3>
+<p>Enabling your product for the world market simply makes economic sense. And
+ the steps above show that the process is relatively straightforward. Now here's
+ that quiz we mentioned in the introduction:</p>
+<blockquote>True or False: The majority of IBM's worldwide
+software sales revenue is within the United
+States.</blockquote>
+<p>
+False. Indeed, more than 50% of IBM software revenue
+comes from outside the United States.</p>
+<p>Fortunately,
+those developers with products based on the Eclipse platform
+benefit from having ready translations of
+the base product. All that is left is to
+follow the clear steps outlined in this article
+to open your Eclipse-based product to a worldwide
+market!</p>
+<H4><a name="glossary">Glossary</a></H4>
+<p>
+<i>Codepoint</i>
+<br />
+ Characters can be represented by one or more bytes of information. Codepoints
+ are the hexadecimal values assigned to each graphic character.</p>
+<p>
+<i>Codepage</i>
+<br />
+ A codepage is a specification of code points for each graphic character in
+ a set, or in a collection of graphic character sets. Within a given codepage,
+ a codepoint can have only one specific meaning. You can display the active
+ codepage on the Windows&#174; operating system with the CHCP command (only one codepage is active at any given moment).</p>
+<p>
+<i>Encoding</i>
+<br />
+ The codepage associated with a given piece of data. A file is said to be "encoded"
+ in a given code page; for example, Notepad will encode its data in code page
+ 437 on a US-English machine by default. The <b>Save As</b> dialog allows the
+ user to select several other possible encodings, Unicode and UTF-8 most notable
+ among them.</p>
+<p>
+<i>Internationalization (sometimes abbreviated "I18N")</i>
+<br />
+ Internationalization refers to the process of developing programs without prior
+ knowledge of the language, cultural data, or character encoding schemes they
+ are expected to handle. In system terms, it refers to the provision of interfaces
+ that enable internationalized programs to change their behavior at run time
+ for specific language operation.</p>
+<p>
+<i>Single-Byte Coded Character Set (SBCS)</i>
+<br />
+ In a single-byte coded character set, a one-byte codepoint represents
+ each character in the set. Typically, SBCS is used to represent the characters
+ of the English language, the European languages, the Cyrillic languages, the
+ Arabic language, and the Hebrew language, to name a few.</p>
+<p>
+<i>Double-Byte Coded Character Set (DBCS)</i>
+<br />
+ In a double-byte coded character set (DBCS), a two-byte codepoint represents
+ each character in the set. Languages that are ideographic in nature, such as
+ Japanese, Chinese, and Korean, have more characters than can be represented
+ internally by 256 code points and thus require double-byte coded character sets.</p>
+<p>
+<i>Localization (sometimes abbreviated "L10N")</i>
+<br />
+ Localization refers to the process of establishing information within a computer
+ system specific to each supported language, cultural data, and coded character
+ set combination.</p>
+<p>
+<i>Mixed-Byte Character Set</i>
+<br />
+ A mixed-byte coded character set is a set of characters containing both single-byte
+ characters and double-byte characters. On the MBCS, each byte of data must be
+ examined to see if it is the first byte of a double-byte or single-byte character.
+ If the byte is in a certain range (greater than X'80', for example), then it
+ is the first byte of a double-byte character.</p>
+<p>
+<i>NLS</i>
+<br />
+ National Language Support.</p>
+<p>
+<i>Unicode</i>
+<br />
+ Directly from <A href="http://www.unicode.org">http://www.unicode.org</A>: "Unicode
+ provides a unique number for every character, no matter what the platform, no
+ matter what the program, no matter what the language."
+<br />Note: While it is true that Java text manipulation classes are Unicode-centric,
+ this is often not the case for data stored outside of your program's auspices.
+ Java programmers must take into consideration the data encoding by performing
+ local codepage-to-Unicode transformations where necessary.</p>
+<H4><a name="unicode_table">Unicode codepoints of common accented Latin characters</a></H4>
+<table width="39%" border="1" cellpadding="0" cellspacing="0">
+
+
+ <tr bgcolor="#CCCCCC">
+ <td colspan="2">
+ <div align="center"><b>Characters</b></div>
+ </td>
+ </tr>
+ <tr>
+ <td width="48%">\u00e0 </td>
+ <td width="52%">a grave</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00e1</td>
+ <td width="52%"> a acute</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00c0 </td>
+ <td width="52%">A grave</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00c1 </td>
+ <td width="52%">A acute</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00c2 </td>
+ <td width="52%">A circumflex</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00e2</td>
+ <td width="52%">a circumflex</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00c3 </td>
+ <td width="52%">A tilde</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00e4 </td>
+ <td width="52%">a dieresis</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00c4 </td>
+ <td width="52%">A dieresis</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00e8 </td>
+ <td width="52%">e grave</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00c8 </td>
+ <td width="52%">E grave</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00e9 </td>
+ <td width="52%">e acute</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00c9 </td>
+ <td width="52%">E acute</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00ea </td>
+ <td width="52%">e circumflex</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00eb </td>
+ <td width="52%">e dieresis</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00cb </td>
+ <td width="52%">E dieresis</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00ea </td>
+ <td width="52%">e circumflex</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00ca </td>
+ <td width="52%">E circumflex</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00ef </td>
+ <td width="52%">i dieresis</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00ec</td>
+ <td width="52%"> i grave</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00ed </td>
+ <td width="52%">i acute</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00cc</td>
+ <td width="52%"> I grave</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00cd </td>
+ <td width="52%">I acute</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00ee </td>
+ <td width="52%">i circumflex</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00ce </td>
+ <td width="52%">I circumflex</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00f6 </td>
+ <td width="52%">o dieresis</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00d6 </td>
+ <td width="52%">O dieresis</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00e3 </td>
+ <td width="52%">a tilde</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00f4 </td>
+ <td width="52%">o circumflex</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00d4 </td>
+ <td width="52%">O circumflex</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00f2 </td>
+ <td width="52%">o grave</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00d2 </td>
+ <td width="52%">O grave</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00f3 </td>
+ <td width="52%">o acute</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00d3 </td>
+ <td width="52%">O acute</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00f5 </td>
+ <td width="52%">o tilde</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00d5 </td>
+ <td width="52%">O tilde</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00f1 </td>
+ <td width="52%">n tilde</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00d1 </td>
+ <td width="52%">N tilde</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00f9 </td>
+ <td width="52%">u grave</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00d9 </td>
+ <td width="52%">U grave</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00fa </td>
+ <td width="52%">u acute</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00da </td>
+ <td width="52%">U acute</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00fb </td>
+ <td width="52%">u circumflex</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00db </td>
+ <td width="52%">U circumflex</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00fc </td>
+ <td width="52%">u dieresis</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00dc </td>
+ <td width="52%">U dieresis</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00df </td>
+ <td width="52%">s sharp</td>
+ </tr>
+ <tr bgcolor="#CCCCCC">
+ <td colspan="2">
+ <div align="center"><b>Special symbols</b></div>
+ </td>
+ </tr>
+ <tr>
+ <td width="48%">\u00ba </td>
+ <td width="52%">masculine ordinal indicator</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00a7 </td>
+ <td width="52%">section sign</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00aa </td>
+ <td width="52%">feminine ordinal indicator</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00ac </td>
+ <td width="52%">not sign</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00b9 </td>
+ <td width="52%">1 superscript</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00b2 </td>
+ <td width="52%">2 superscript</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00b3 </td>
+ <td width="52%">3 superscript</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00a3 </td>
+ <td width="52%">pound sign</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00a2 </td>
+ <td width="52%">cents sign</td>
+ </tr>
+ <tr>
+ <td width="48%">\u00b0 </td>
+ <td width="52%">degree sign</td>
+ </tr>
+
+
+</table>
+<h3><A name="authors" />About the authors</A><A name="authors" /><BR><BR>
+</A></H3>
+<P><A name="authors" /><B>Dan Kehn</B> is a Senior Software Engineer at IBM in
+ Research Triangle Park, North Carolina.
+ His
+ interests in object-oriented programming
+ go back to 1985, long before it enjoyed
+ the
+ acceptance it has today. He has a broad
+ range
+ of software experience, having worked
+ on
+ development tools like VisualAge for
+ Smalltalk,
+ operating system performance and memory
+ analysis,
+ and user interface design. Dan worked
+ as
+ a consultant for object-oriented development
+ projects throughout the U.S. as well
+ as four
+ years in Europe. His recent interests
+ include
+ object-oriented analysis/design, programming
+ tools, and Web programming with the
+ WebSphere
+ Application Server. Last year he joined
+ the
+ Eclipse Jumpstart team, whose primary
+ goal
+ is to help ISVs to create commercial
+ offerings
+ based on the Eclipse Platform. In another
+ life, Dan authored several articles
+ about
+ diverse Smalltalk topics like meta-programming,
+ team development, and memory analysis.
+ You
+ can find them on</A>
+<A href="http://www.ibm.com/software/ad/smalltalk/discussion/index.html">Eye on SmallTalk</A>.
+
+<P><B>Scott Fairbrother</B> works on the Eclipse Jumpstart team at IBM in Research Triangle Park,
+North Carolina. He is a software developer with over 20 years of experience.
+He has developed object-oriented application frameworks for business process
+management. He has written specifications for IBM middleware on Windows
+2000 and has also authored on the subject of Microsoft Visual Studio .NET.</P>
+<P><A name="authors" /><B>Cam-Thu Le</B> joined IBM in 1983. Cam's experience spans
+ many aspects of software creation:
+development,
+ testing, and National Language Support
+(NLS)
+ planning and coordination. Cam has
+led the
+ National Language versions of IBM products
+ to worldwide concurrent general availability,
+ including the 4690 Point of Sales product
+ and VisualAge for Smalltalk. Cam joined
+the
+ Eclipse Project last year as the NLS
+focal
+ point. Cam coordinated the building
+and testing
+ of the NL versions of the Eclipse Workbench
+ and WebSphere Studio Workbench.</A>
+
+
+</BODY>
+</html>
diff --git a/Article-Internationalization/images/Idea.jpg b/Article-Internationalization/images/Idea.jpg
new file mode 100644
index 0000000..119ce70
--- /dev/null
+++ b/Article-Internationalization/images/Idea.jpg
Binary files differ
diff --git a/Article-Internationalization/images/envelope.jpg b/Article-Internationalization/images/envelope.jpg
new file mode 100644
index 0000000..57f72ea
--- /dev/null
+++ b/Article-Internationalization/images/envelope.jpg
Binary files differ
diff --git a/Article-Internationalization/images/fraggen1.jpg b/Article-Internationalization/images/fraggen1.jpg
new file mode 100644
index 0000000..e7d4335
--- /dev/null
+++ b/Article-Internationalization/images/fraggen1.jpg
Binary files differ
diff --git a/Article-Internationalization/images/fraggen2.jpg b/Article-Internationalization/images/fraggen2.jpg
new file mode 100644
index 0000000..6d4ea9e
--- /dev/null
+++ b/Article-Internationalization/images/fraggen2.jpg
Binary files differ
diff --git a/Article-Internationalization/images/fraggen3.jpg b/Article-Internationalization/images/fraggen3.jpg
new file mode 100644
index 0000000..50fdba8
--- /dev/null
+++ b/Article-Internationalization/images/fraggen3.jpg
Binary files differ
diff --git a/Article-Internationalization/images/image2.jpg b/Article-Internationalization/images/image2.jpg
new file mode 100644
index 0000000..30e074d
--- /dev/null
+++ b/Article-Internationalization/images/image2.jpg
Binary files differ
diff --git a/Article-Internationalization/images/image20.jpg b/Article-Internationalization/images/image20.jpg
new file mode 100644
index 0000000..337b5f6
--- /dev/null
+++ b/Article-Internationalization/images/image20.jpg
Binary files differ
diff --git a/Article-Internationalization/images/image23.jpg b/Article-Internationalization/images/image23.jpg
new file mode 100644
index 0000000..fa732c0
--- /dev/null
+++ b/Article-Internationalization/images/image23.jpg
Binary files differ
diff --git a/Article-Internationalization/images/image24.jpg b/Article-Internationalization/images/image24.jpg
new file mode 100644
index 0000000..34215e5
--- /dev/null
+++ b/Article-Internationalization/images/image24.jpg
Binary files differ
diff --git a/Article-Internationalization/images/image25.jpg b/Article-Internationalization/images/image25.jpg
new file mode 100644
index 0000000..4089cb6
--- /dev/null
+++ b/Article-Internationalization/images/image25.jpg
Binary files differ
diff --git a/Article-Internationalization/images/image26.jpg b/Article-Internationalization/images/image26.jpg
new file mode 100644
index 0000000..dbcdb21
--- /dev/null
+++ b/Article-Internationalization/images/image26.jpg
Binary files differ
diff --git a/Article-Internationalization/images/image28.jpg b/Article-Internationalization/images/image28.jpg
new file mode 100644
index 0000000..7c17770
--- /dev/null
+++ b/Article-Internationalization/images/image28.jpg
Binary files differ
diff --git a/Article-Internationalization/images/image6.jpg b/Article-Internationalization/images/image6.jpg
new file mode 100644
index 0000000..a501b9f
--- /dev/null
+++ b/Article-Internationalization/images/image6.jpg
Binary files differ
diff --git a/Article-Internationalization/images/image7.jpg b/Article-Internationalization/images/image7.jpg
new file mode 100644
index 0000000..8458b33
--- /dev/null
+++ b/Article-Internationalization/images/image7.jpg
Binary files differ
diff --git a/Article-Internationalization/images/image8.jpg b/Article-Internationalization/images/image8.jpg
new file mode 100644
index 0000000..542f002
--- /dev/null
+++ b/Article-Internationalization/images/image8.jpg
Binary files differ
diff --git a/Article-Internationalization/images/image9.jpg b/Article-Internationalization/images/image9.jpg
new file mode 100644
index 0000000..04a5f6c
--- /dev/null
+++ b/Article-Internationalization/images/image9.jpg
Binary files differ
diff --git a/Article-Internationalization/images/linux_only.gif b/Article-Internationalization/images/linux_only.gif
new file mode 100644
index 0000000..7c135cf
--- /dev/null
+++ b/Article-Internationalization/images/linux_only.gif
Binary files differ
diff --git a/Article-Internationalization/images/mailbox.jpg b/Article-Internationalization/images/mailbox.jpg
new file mode 100644
index 0000000..a2260df
--- /dev/null
+++ b/Article-Internationalization/images/mailbox.jpg
Binary files differ
diff --git a/Article-Internationalization/images/nav3.jpg b/Article-Internationalization/images/nav3.jpg
new file mode 100644
index 0000000..035d74e
--- /dev/null
+++ b/Article-Internationalization/images/nav3.jpg
Binary files differ
diff --git a/Article-Internationalization/images/never.jpg b/Article-Internationalization/images/never.jp