Projects Tools Projects Hosted Projects
|
ativan data
viagra alternative
drug fioricet
carisoprodol buying
tramadol
levitra alternative
discount phentermine
ambien side effects
canada discount celexa
buy tadalafil
alprazolam
xanax online
valium
buy ultram online
cialis online
butalbital buy online
buy soma
atenolol and flushing
drug ultracet
butalbital prescription
ativan buy online
buy online ultram
butalbital buying
tramadol
getting alprazolam without a prescription
generic valium
buy cheap ultracet
soft tab tadalafil
adipex dangers
carisoprodol
atenolol side effects
side effects of xanax
viagra alternative
buy cialis
drug fioricet
levitra
buy ambien online
discount phentermine
buy online celexa
is ultracet a narcotic
viagra
phentermine
ambien
xanax
buy diazepam
cialis online
buy tadalafil
is ultracet a narcotic
butalbital
buy online celexa
buy fioricet online
ativan data
adipex
levitra
carisoprodol buying
generic valium
tramadol cod
atenolol medication
buy alprazolam online
atenolol side effects
life insurance
uk mortgage advice
reverse mortgages
no down payment mortgage loans
affordable health insurance
online debt consolidation
home mortgage
debt consolidation credit counseling
commercial mortgage lender
disability income insurance
medicare supplemental health insurance
second mortgage
second mortgages
online personals dating services
internet dating service
russian women dating
latin euro dating
dating services
uk dating
matchmaking dating services
dating photo personal ads
yahoo personnel dating
dating sex
boston dating
on line dating services
internet dating services
free poker
gamble
baccarat crystal
online sports gambling
rolex
texas holdem poker
online betting
las vegas casino
free slot machines
online roulette game
online casinos
bet uncut
online casino roulette
allstate life insurance
refinance mortgage
california reverse mortgage
georgia mortgage companies
mortgage loans
cheap life insurance
castle point mortgage
free term life insurance quote
online debt consolidation
provident life insurance
pay off mortgage principal or interest
commercial mortgage broker
allstate insurance company
las vegas casino jobs
online casino gambling
football betting
proctor & gamble
casinos
baccarat crystal
antique slot machines
free blackjack
roulette online
rolex replica
online poker
bet
internet gambling
viagra
is ultracet a narcotic
butalbital prescription
adipex prescriptions
phentermine
generic ambien
levitra alternative
side effects of xanax
tramadol cod
cheap soma
online atenolol
diazepam
generic cialis
ativan buy online
canada discount celexa
carisoprodol buying
drug fioricet
generic ultram
generic tadalafil
drug fioricet
tramadol
buy ambien
adipex
buy online carisoprodol
buy ultram
what does alprazolam look like
buy soma
buy cheap fioricet
viagra alternative
canada discount celexa
butalbital prescription
buy levitra
ativan buying
buy xanax
phentermine 37 5mg
generic valium
buy cheap diazepam
tadalafil alternative
atenolol
buy cheap carisoprodol
buy viagra
drug ultracet
valium without prescription
alprazolam online
ambien online
cialis online
buy atenolol
cheap soma
ativan cheap
carisoprodol buy online
buy xanax
online pharmacy tramadol
phentermine online
buy tadalafil
diazepam buy online
buy ultram
celexa
butalbital cheap
adipex diet pills
cheap ultracet
generic tadalafil
buy soma
generic valium
carisoprodol buy online
xanax xr
cheap fioricet
buy ultracet
diazepam
butalbital buy online
generic levitra
phentermine 37 5mg
ambien online
adipex diet pills
buy cheap celexa
buy atenolol
ativan buy online
order cialis
viagra alternative
cheap tramadol
buy ultracet
generic viagra
buy tadalafil
xanax
cheap ultracet
discount phentermine
getting alprazolam without a prescription
levitra
buy ambien online
buy soma cheap
adipex online
online pharmacy tramadol
butalbital buy online
generic valium
atenolol
celexa
generic cialis
cheap fioricet
buy carisoprodol
buy cheap ultram
buy carisoprodol
generic valium
adipex diet pills
ambien side effects
cheap ultracet
viagra
cheap cialis
ativan cheap
buy alprazolam online
buy online celexa
tramadol
butalbital buy online
carisoprodol
cheap levitra
cheap diazepam
buy atenolol
buy fioricet online
buy xanax
buy tadalafil
buy soma online
canada discount celexa
What this page is about and what you should know before reading it :This page is intended to give somebody interested in GEF most of the things he has to know to get started. This includes a description of the purpose of the library, a global view of the library with descriptions of the different components and how to use them, and some practical guidelines to build a simple GEF editor. At least that's what I have tried to do. I wrote most of this for myself a few months ago but I think this is better here than on my personal hard drive. Maybe it could be useful to you. I didn't try to avoid redundancy with currently available documentation. When I got started, I read the Randy Hudson tutorial, the IBM redbook and the docs of the library. So what is written here is probably strongly inspired by all that. My mother tongue is French, I am not an experienced eclipse and GEF programmer and I really don't feel like some kind of genius. So what follows probably contains mistakes, and is by far not so reliable as the official docs. Feel free to correct all the mistakes you notice and to add your own content to the page. There are a lot of todo's in the page, feel free to complete them if you want to. Please leave comments to point out what you don't understand, what is not clear, what you would like to find here and things like that. rlemaigr 1) The problem GEF helps you to solve :GEF stands for Graphical Editing Framework. So this is a library to ease the task of building a graphical editor, in Eclipse.
You want to build an application with the following requirements :
Such an application providing the user with a way to modify a model graphically is called a graphical editor. The view, the model and the link between them are illustrated in this picture, which introduces the symbolic conventions I will try to follow for the rest of this page:
In this general problem, the link between the model and the view can be anything, so it is possible that for two identical states of the model, the view showed to the user is different. For example, if the user can move the different figures of the view without any trace being kept of their positions in the model, there will be several possible views for a same state of the model (one for each possible location the user can choose for the figures in the view). Your graphical editor should work like that :
But defined like that, I think that this problem is too fuzzy to start a good explanation, and to give clear ideas to people who want to get started with GEF. So I will define a problem which is less general and I will try to show in this page how GEF allows you to solve this less general problem. Anyway, I may be wrong but I think that GEF was thought to solve that less general problem, and even if it wasn't, I believe that it is good practice to follow the limitations introduced by the less general problem to keep things clear and simple.
This problem is just the same as above except that this time the link between the model and the view is more specific : for each state of the model, you have defined one view which should be displayed to the user for that particular state. So this time the view shown to the user depends only on the current state of the model and is fully defined by it : the view is a function of the state of the model. This is illustrated on this picture : This loss of generality leads to a simplification of the architecture of the application : now the user's actions on the graphical interface can be interpreted in terms of model modifications only because we know that the new view will be fully defined by the new state of the model, whatever were the user actions on the GUI. We can make a clean separation between :
This is illustrated in these pictures : Please don't get me wrong : the model is not really responsable of updating the view. This is just a schematic view of what happens when the user acts on the GUI. Some pieces are absent from the picture. To implement this, you have three problems to solve :
These are the problems that GEF helps you to solve and the following explanations will look at them one by one. 2) Model - view - controller architecture :I know what your are thinking : you are thinking that this section is only made for those masochists of us who absolutely want to know how the things work in the GEF black box and so you can skip it. Don't think that ! Because :
So please read this before going further, this is not a waste of time.
The model - view - controller architecture (MVC) is a software architecture which applies to graphical editors. I will explain some of the advantages of this architecture later. All the pieces of GEF are built to take place into this architecture. But the right implementation of this architecture with GEF is up to you.
I think everybody has an intuitive view of what this term means so I will not try to define it more clearly. However, there are some requirements about the model that must be known :
GEF doesn't assume anything about the model you use. This means that you can use almost every model with GEF, and this is good news. But on the other hand, this also means that you will have to take care of the preceding requirements by yourself ! In particular you will have to implement by yourself the notification mechanism, and the listeners for it. But this is easy to do because there are some ready-to-use supports for notification in Eclipse and in the java.beans package. I will give examples of that later.
The view is the set of building blocks which compose the graphical interface. As for the model, the MVC architecture specifies some requirements for the view :
In the rest of the page, I will assume that the view is built with Draw2d Figures. GEF provides support for Draw2d Figures and for some kind of tree item figures, but I have never used the second ones so I can't talk about them. I believe (?) that GEF can be used with other kinds of graphical objects than tree figures and Draw2D Figures but it doesn't provide as much support for them as it does for Draw2d figures and for the tree items. I will give a very little description of Draw2d later but only what is necessary to understand GEF.
As the model doesn't hold any references to the view and as the view doesn't hold any references to the model, you should be wondering what makes the link between the two. This link is made by the controllers. In GEF the controllers are subclasses of EditPart. There is an EditPart between each model object which has to be graphically represented and its view. The EditPart knows about the two of them (it holds a reference to the model object and to its view) so it is able to gather information about the model object, and to set the graphical properties of the view. The EditPart is registered as a listener of its model object to be informed about its changes, and when these changes occur, it knows how to update the view according to the new state of the model object. The controller is also involved in the editing process of its model object in some way. This will be explained later.
Here is an illustration to summarize all this : So now you should have a good idea about how the changes in the model result in an update of the view, and about which elements are involved in this process. But you still don't know how the actions of the user are translated into changes of the model. This involves too many things that are still to be introduced so it will be explained later. Remember that this picture doesn't show how GEF works, it shows how you will have to assemble the different pieces provided by GEF.
First of all, GEF is built to be used like this. So if you don't, you will have a lot of problems. There are many advantages to use this architecture, here are the ones that come to my mind by now :
3) A short description of Draw2d :I give here a description of Draw2d, but just the basic knowledge which is necessary to understand GEF. To build a nice GEF editor, with a nice GUI it will not be sufficient, but to follow the rest of the explanations, it should be enough.
Draw2d is a lightweight system of graphical components which follows the same philosophy as Swing. But unlike swing which has its own MVC architecture, Draw2d is almost purely graphical. There are no draw2d models behind what is shown on the screen, so you won't find in draw2d things like JTables, JList, JTextField, and things like that. Its purpose is only to show things on the screen, not to hold and manipulate any data.
Figures are the building blocks of Draw2d. A Draw2d GUI is defined by a tree of Figures used by the lightweight system to paint the GUI. You can add a Figure to its parent by calling parent.add(child) and remove it by calling parent.remove(child). But what is the meaning of this tree ? What does it change to put some Figure as a child of a parent A or as a child of a parent B ? The Figure class implements the IFigure interface which defines it and which is used in every place where only the generic properties of all the figures are needed. Draw2d provides a lot of useful ready-to-use figures.
Figures have the ability to paint themselves (there is a Figure.paint(Graphics) method).
The tree of figures is painted recursively by calling paint(Graphics) on the root figure. The last two remarks define the painting order of the figures, and thus they define which figure is above another, like this : So if A is a child of B in the figures tree, it means that A will be painted above B.
This is not an easy thing to explain because the usage made of the bounds by draw2d differs from some figures to others. Each Figure has bounds. For the large majority of the figures, the bounds can be set (for some others, they are calculated based on the content of the figure). Bounds define a rectangular area outside of which the clipping system of draw2d forbids any painting of the figure or of its children. Each figure is supposed to fill at best the bounds allocated to it with the content it has to display. The limitation of the space allocated to a figure for painting allows some very important improvements in the painting algorithm. The clipping windows associated with each figure of a tree are shown here :
So if A is a child of B in the figure tree, A will not be allowed to paint itself outside of the bounds of B. Moreover, if you set the bounds of a figure in such a way that it moves, then all the children tree will move the same.
4) Building the view when the editor is opened:This is the first problem which GEF helps you to solve to build a graphical editor. You have a model, and you want it to be displayed to the user in some way for the first time, when you open the editor. In fact, the problem of creating the view is not really different from the problem of updating the view but I have decided to separate them because it makes the things a lot easier to explain. The elements involved in the creation of the view are :
Once again, this is not just an explanation of what happens in the GEF black box : if you understand how the view gets built, you will know how to write the code to build the view which suits your needs. Once you have read this section, you will be able to write a code which automatically builds the view associated with your model when the editor is opened. But there will still be no updating of this view if the model changes, and no editing capabilities provided to the user.
For each model object you want to be represented in the view, you will have to write three things :
The view of a model object doesn't have to be a single Figure. It will more likely be a subtree of Figures : You may wonder about one thing in this picture : the content pane. I didn't talk about that thing till now. Sorry, this will be explained later. For now think about it as a leaf of the figure subtree which serves as a container in the view of the model object and can be filled by GEF with some things if it is needed. You don't necessarily have to explicitly define a content pane. If you don't, GEF will use the root figure of the subtree as the content pane. Example:
Figure to represent a person
Now you should wonder where you have to write the code to instanciate the view associated with a model object, and where you have to write the code to fill the view with the data from the model object to display. You already know that the controller links the view object to the model object and knows about them. So you may already guess the answer : this code belongs in the EditPart between the view object and the model object and I will explain how to do this in the next section.
This picture shows how the EditPart takes place between the model object and its view : The EditPart knows about two things in the Figures subtree of the view of the model object :
The base class for EditParts using Draw2d Figures is AbstractGraphicalEditPart. Each AbstractGraphicalEditPart links a model object to its view. You can set/get the model object associated with an EditPart by calling setModel(Object) and getModel(Object). You can get the (root) Figure associated with an AbstractGraphicalEditPart by calling getFigure(). You cannot set this figure, it is built by GEF when it is needed. So now you have different types of model objects to represent, and you have written the Figure classes (and possibly interfaces) to represent each of these types of model objects. For each type of model object to link to a view, you have to write a subclass of AbstractGraphicalEditPart which will link this type of model object to its view. For each of the AbstractGraphicalEditPart subclasses, you have some methods to implement / override (more will come later, here are just the ones necessary to allow GEF to build the view) :
You can see that the createFigure(), getContentPane() and getModelChildren() methods are protected. So you will not have to call them, they will be called by GEF in the process of building the view when it is needed. The way these methods are used by GEF will become clearer later, for now, just try to understand which code you have to put in them.
To continue with the same example as before, suppose you want to represent a Person model object and that you have written a PersonFigure class and an IPersonFigure interface like before.You now have to write a PersonEditPart which extends AbstractGraphicalEditPart to link the Person model objects with the PersonFigures. For the createFigure() method, you would just have to write:
This is very simple too. You just have to get a reference to the model object, another one to the view and then you get the data from the model and apply them to the view :
If you have defined a content pane, it should be accessible through your figure interface so you write :
You will get a better idea of what you have to put in this method when you see how the view is built by GEF. I give here a little explanation for you to get the general idea. A lot of models must be represented as a containement hierarchy, with parent views containing their child views (this does not mean that the model itself has to be a tree, I'm talking about the view here). If you consider a UML diagram, then the diagram contains the classes, the classes contain the attributes and the methods, and the methods contain some parameters. Each EditPart has to implement the getModelChildren() method to return to GEF the List of model objects which must be represented as children of the content pane of the EditPart. When GEF creates the EditParts and figures for these model objects, their EditParts will be added as children of the current EditPart and their figures will be added as children of the content pane of the current EditPart. In the example, the Fruits objects have to be represented as children of the content pane of the PersonEditPart, so we implement the getModelChildren method like that :
An EditPartViewer is reponsible for installing one view of your model on a SWT Control. Nothing prevents you from creating multiple views of your model, each of them with its own EditParts and Draw2d Figures, and each of them will be installed on an SWT Control with an EditPartViewer. If your view is composed with Draw2d Figures, you will have to use a subclass of EditPartViewer : GraphicalViewer. You give it the Control, an EditPartFactory, a RootEditPart and a model object called the content and it will display your model to the user. It is also responsible for some other things which concern the editing capabilities but I can't explain them now without having to introduce new GEF elements so I will leave it for later. The EditParts are organized in a tree structure. You will understand what this structure is when you see how the view of your model is built. The root of this structure is the RootEditPart. The figure associated with the RootEditPart is composed of a set of stacked draw2d Layers where the different elements of the view will take place. So by choosing which RootEditPart you will use, you also choose some properties of the view, like its ability to be scrolled, scalled, and things like that. GEF provides a few implementations of RootEditPart, you can look in the javadoc for a description of each of them and choose the one which suits your needs. Don't worry too much about this, it is not the important part of the work and you can copy/paste some code to create this part of your editor from some example. What is important (for now) are the model, the EditParts, the Figures and the EditPartFactory. Some other roles of EditPartViewer are :
[ TODO : write a code snippet showing the GraphicalEditorPart subclass for the installation of a GraphicalViewer with a FreeformRootEditPart to show a model (if somebody could do that...). ]
In the process of building or refreshing the view installed on a particular EditPartViewer, GEF often needs to create the proper EditPart to represent some model object in this EditPartViewer. When GEF needs it, it asks the EditPartFactory of the EditPartViewer to build an EditPart for the model object to represent in that EditPartViewer. So you have to implement an EditPartFactory yourself for each EditPartViewer you use. Here are the interface provided by GEF for EditPartFactory and an example : EditPartFactory interface :
Example :
Now we have all we need to understand the way GEF builds the view. First I will describe what is built and how it depends on the code you have written, and then I will describe how it is built in a more detailled way. Here is a picture which describes the process approximately : Here is a chronological description of what happens during the building of the view.
An alternative to EditPartFactory : Each EditPart has the responsability to build its own children EditParts given the list of the model objects which should be represented as children of the content pane returned by getModelChildren(). This is the job of the EditPart.createChild(Object model) method. By default, this method gets the EditPartFactory of the viewer the EditPart belongs to and delegates the job to it. But if you don't like this default behaviour, you can override the createChild method to build the child EditPart given a model object (the context EditPart is no longer needed as parameter because the context EditPart is this).
This section summarizes the different ways you hook into the process of building the view, and their effects. The EditPartFactory defines which EditPart class will be associated with each type of model object, and each EditPart class defines which type of view will be associated with its model through its methods createFigure() and refreshVisuals(). So by defining the EditPartFactory and the createFigure() and refreshVisuals() methods of the EditParts and the Figures, you define the view associated with each model object and the link between the properties of each model object and the graphical properties of its view. The getModelChildren() methods of the EditParts defines the structure of the view, i.e., which model objects will be represented "inside" (in the content pane of) the representation of another model object. So by defining the getModelChildren() methods of the EditParts, you define the tree structure of the view.
But there is one question left : which model objects must be represented with EditParts and their associated Figures, and which model objects must simply be represented as a property of the view associated with another model object, without an associated EditPart ? For example, if you want to represent a person, with a name and a surname, you could think at least about two different things : And you could also think about using only one big EditPart to link the whole model to the whole view (but it would be a very very bad idea). So what is the right thing to do ? How can you choose the right "granularity" of the EditParts ? The choice is up to you but there are some things to keep in mind when you make your choice about this :
Suppose you want to represent in the view of a Person the list of the fruits, but also the list of the vegetables he likes eating and you want to separate the list of the fruits and the list of the vegatables. This is a problem because GEF only allows one content pane by EditPart. So what can you do ? If you want the fruits grouped in a content pane and the vegetables grouped in another content pane, you don't have the choice : you have to provide two EditParts, one with a content pane containing the fruits and with a getModelChildren method returning the list of the fruits, the other one for the vegetables, and these two EditParts have to be children of the PersonEditPart in order to subdivide its content pane artificially. Like that : These two new EditParts must listen to the Person model object to receive events when a fruit or a vegetable is added to the Person model and call refreshChildren on themselves when that happens (I suppose here the lists are too dumb to notify their changes themselves). But what will be the model of these EditParts and how will you build them ? This was not shown on the picture. If you set the model of these two EditParts as the Person object, there will be three EditParts with the same model and that will cause problems because the EditPartViewer maintains a Map [model objects -> EditParts] and that map allows only one EditPart by model object. Only the last created EditPart with the Person object as its model will be in the Map and that could be annoying later. If the fruits and vegetables lists are directly accessible, then you could choose to set them as the models of the new EditParts. But what if they are not ? I give here the solution I have found in this case, I don't know if it is the good solution but it seems to work : PersonEditPart :
[note: this code snippet includes some elements which will be explained in the next section (updating the view), you may want to read the next section before reading this] FruitsListEditPart :
5) Updating the view when the model is changed :
If you remember the MVC pattern I explained before, the model must notify its changes to its listeners. Here is an example for the class Person, like before : Example :
In the MVC pattern, the controllers must listen to the changes of the model. In GEF, EditParts are the controllers so they must listen to their model to update the view according to the new state of the model. When an EditPart is added to the EditParts tree and when its figure is added to the figure tree, the method EditPart.activate() is called. When an EditPart is removed from the EditParts tree, the method deactivate() is called. So these are the good places to hook / unhook the EditPart to / from its model. Here is an example for the class PersonEditPart : Example :
Don't forget to unhook an EditPart in its deactivate method ! If you don't, some repainting/revalidating code could be called on its figure when events are fired by the model but as its figure is no longer part of the figure tree, this could cause weird errors which would make you scratch your head for days.
When the model evolves, you always want that :
GEF provides two methods to help you to achieve this goal :
The refreshChildren() method compares the model objects of the children EditParts of an EditPart to the List of objects returned by its getModelChildren() method. Then it creates new EditParts for the model objects which are represented in the getModelChildren() List but not already represented as model of children EditParts of the EditPart, and it drops the children EditParts which have a model which is not in the getModelChildren() List. So after calling the refreshChildren() method, the children EditParts of the EditPart are the ones defined by its getModelChildren() method, as desired. You have to call yourself these two methods on an EditPart in response to events fired by the model object of this EditPart. Here is an example of this for the PersonEditPart class : Example :
Goto page 2Comments:From diwant - 3/15/06 6:25 PM From mateu - 2/7/06 1:01 AM I'm reading your document and I wanted to do a 'correction'. When you say that EditPart provides workbrench ISelectionService that enables to get selected EditParts you say that you are not sure. It is true. Somethin like that will do it (returning a list of the selected editParts: if (!(viewer.getSelection() instanceof IStructuredSelection)) From kaliask - 11/24/05 5:46 PM I can't see all the diagrams on this page. Can you please fix the page. From n16er - 6/8/05 12:55 PM I'm brand new to GEF and therefrore not too keen on fixing what appears to be a mistake in this fine article but I'll point out the issue all the same hoping one of you more experienced fellows will concur. In section 4.8 in the listing for FruitListEditPart in the method getModelChildren() it seems to me that
Person p = (Person)getModel(); is incorrect and should be Person p = (Person)getParent().getModel();What say the rest of you? From RudyBOne - 2/16/05 8:32 AM Excellent article. Need a way to print the article however. Printing the web page directly causes the right edge of the article to be cut off. I had to copy the article body and paste it to a word document to get it to print.
From sbl - 11/30/04 11:58 PM I think this page is a very good introduction into GEF :-).
With GEF it's possible to build plugins for eclipse. So it would also be useful to show how to setup a plugin project in eclipse and get it run. Yours sbl From Frank [217.9.29.85] - 10/8/04 12:26 PM I suggest renaming the "next"-link to somehting like "...go to in part 2". It`s easily missed, i know I missed it the first few times.
From dhiraj [196.12.47.2] - 10/5/04 11:06 AM Good piece of work. Neatly explained ...was quite helpful to me
thanx From rlemaigr [80.201.136.35] - 9/12/04 1:10 PM You're probably right. I was wondering why the horizontal scrollbar was there...I will correct it, thank you for your advice.
From frank [217.9.27.150] - 9/12/04 12:02 PM Please make sure the program code (mostly the comments) in the grey boxes is not to wide. Else the text doesn't wrap and you have to scroll vertically to read.
From rlemaigr - 9/4/04 8:29 PM Please log in and describe the changes you made when you make some. "typo" seems to have change something lately but I don't know what. I'm modifying the page offline on my HD, so if somebody makes a change and doesn't describe it, there is a risk it will be deleted when I upload the new version of the page. Thanks.
From rlemaigr - 9/2/04 3:21 PM You've got mail !
The mail address I used is the one mentioned here:
http://www-106.ibm.com/developerworks/opensource/library/os-gef/#author1
(sorry for the pieces that I...a-hem..."borrowed" from the official documentation but as I was trying to promote your work with them, I believed that there shouldn't be too much complaints about this :D )
From Randy Hudson [129.33.49.251] - 9/2/04 9:39 AM Very nice! How about we make this thing official? If you want to contribute this to Eclipse.org, we can look into the copyright issues and your donating it. The diagrams you made are great. Some pieces look familiar :-) From john Lee [63.187.208.187] - 8/31/04 11:52 PM really appreciate your work. Thank you very much.
From absolut [83.130.225.185] - 8/26/04 7:17 PM great job!!! and your greatness is twofold))): first, u covered a very
popular subject - a ground up GEF tutorial. And secondly, u did it in a
very simple and understandable way. thanks a lot))
From Natan [83.130.225.185] - 8/26/04 7:17 PM
great job!!! and your greatness is twofold))): first, u covered a very popular subject - a ground up GEF tutorial. And secondly, u did it in a very simple and understandable way. thanks a lot))
From Natan [83.130.225.185] - 8/26/04 7:16 PM
great job!!! and your greatness is twofold))): first, u covered a very popular subject - a ground up GEF tutorial. And secondly, u did it in a very simple and understandable way. thanks a lot))
From Chhil [66.176.91.101] - 7/7/04 5:18 PM Very impressive...thanx for making it available. I hope this ends up on the eclipse articles page.
From vanto [217.230.8.253] - 6/29/04 8:23 AM
Great work! Thanks!
Last Modified 6/14/06 3:44 PM | Hide Tools |
Somebody has deleted a LOT from this tutorial! Please restore it (I think Version 34 still had the stuff) as this material was very important and useful.
Great tool. Shame someone thinks the comments page is an opportunity for SEO