[Eclipse] Getting Started series of GEF (10. An implementation of table)

Source: Internet
Author: User

In the current GEF version (3.1m6), there are not many available layoutmanagers. In newsgroups, we often see posts requiring more layoutmanagers. Some people also provide their own implementations, for example, this gridlayout is equivalent to the draw2d Implementation of gridlayout in SWT. Although it is certain that more la s will be added for developers in future GEF versions (which may take a long time), there is no direct way to implement table operations using GEF, here I will talk about my practices for your reference only.

The table implementation method depends on the model design. At first glance, we seem to have these classes: table, row, column, and cell ), each model object corresponds to an editpart and a figure. tablepart should contain rowpart and columnpart. The problem is that rowfigure and columnfigure generate a crossover, imagine what layout should your table use to accommodate them? Using such a model is not impossible (for example, using stacklayout), but I think this model requires a lot of extra work, so I use a column-based model.

In my table model, there are only three objects: Table, column, and cell. However, column has a subclass of headercolumn that represents the first column, and cell has a subclass of headercell that represents the cells in the first column, the following two classes are mainly used to simulate the operations on the rows-convert all the operations on the rows to the operations on the headercell. For example, create a new row and convert it to add a new cell in the first column.ProgramAdd a cell to each other column.


Figure 1 Table Editor

The problem now is how to make users unaware that we are operating on cells rather than rows. There are several places to be modified: first, when creating a new line or changing the row position, the insertion prompt line consistent with the row width is displayed, the second is to show the entire row selected when you click the cell (headercell) in the first column. The third is to allow the user to drag the row to change the Row Height, finally, the correct echo image is displayed when the position or size of the row is changed. The following describes their implementation methods in sequence.

Adjust the width of the Inserted Line

In our color palette, there is a row tool item that represents a row in the table. Its role is to create a new row. Note that although this tool item is called row, it is actually used to create a headercell object and create itsCodeAs follows:

Tool = new combinedtemplatecreationentry ("row", "Create a new row", headercell. Class, new simplefactory (headercell. Class), cbmplugin. getimagedescriptor (iconstants. img_row), null );

You can create a new row by dragging it from the palette to the desired position. During the drag process, the editor should be able to display a straight line as the location of the mouse changes, to indicate the position where the new line will be inserted if the mouse is opened at this time. Because this tool represents a cell, by default, GEF will display a line with the same length as the cell. To make the user feel that the row is being inserted, we must change the width of the Inserted Line. The specific method is to overwrite the showlayouttargetfeedback () method in the editpolicy (inheriting flowlayouteditpolicy) of headercolumnpart in charge of layout. The modified code is as follows:

  protected   void   showlayouttargetfeedback (request) {  super  . showlayouttargetfeedback (request);   //   Expand feedback line's width  digoal =  (digoal) gethost (). getparent (). getModel (); column  =  (column) gethost (). getModel (); point P2  = getlinefeedback (). getpoints (). getpoint (1 ); p2.x  = p2.x + (digoal. getcolumns (). size ()-1) * (column. getwidth () +  iconstants. column_spacing); getlinefeedback (). setpoint (P2,  1 ) ;} 

P2 indicates the point on the right of the inserted line. We can add a number to the X coordinate of the line to increase the length of the line, which is related to the number of current columns in the table, it is also related to the column spacing. The calculation method is clear from the code above. The modified result is shown in. When you drag a row to a new position, the same insert line is used.


Figure 2 insert line of the same width as the table

Select the entire row

By default, clicking a cell produces a black border around the cell to indicate the selected status. To allow the user to select the entire row, modify the editpolicy on headercell. As mentioned in the previous post, to modify the editpolicy of a cell as a sub-element of a column, you must return the custom editpolicy in the createchildeditpolicy () method of the editpolicy of columnpart, here, I return the self-implemented dragroweditpolicy, which inherits from the resizableeditpolicy class built in GEF and will be added to the editpolicy list of the child element headercellpart by headercolumnpart. Modify the dragroweditpolicy to select the entire row.

First, it should be noted that the black edges and control points displayed when a graph is selected in GEF are called handle, and the black edges are called movehandle and used to move the graph. the control points are called resizehandle, used to change the image size. To change the size of the Black edge (expanded from the cell width to the width of the entire table), we have to inherit movehandle and overwrite its getlocator () method. The following code is my implementation:

 Public   Class Rowmovehandle Extends Movehandle {  Public  Rowmovehandle (graphicaleditpart owner, locator LOC ){  Super  (Owner, Loc );}  Public  Rowmovehandle (graphicaleditpart owner ){  Super  (Owner );}  //  Calculate the position of the selected row and pass it to movehandlelocator for reference.      Public  Locator getlocator () {ifigure reffigure =New  Figure (); rectangle rect = (Headercellpart) getowner (). getrowbound (); translatetoabsolute (rect); reffigure. setbounds (rect );  Return   New  Movehandlelocator (reffigure );}} 

In the getlocator () method, we call the getrowbound () method of headercellpart to obtain the position and size of the selected row, the code for this method is as follows (put in headercellpart because the editpart object can be easily obtained through getowner () in handle). The calculation method of row size is similar to that of the line inserted before:

PublicRectangle getrowbound () {rectangle rect=Getfigure (). getbounds (). getcopy (); digoal=(Digoal) getparent (). getparent (). GetModel (); column Column=(Column) getparent (). GetModel (); rect. setsize (digoal. getcolumns (). Size ()* Column. getwidth () + (digoal. getcolumns (). Size ()-1 )*Iconstants. column_spacing, rect. getsize (). Height );ReturnRect ;}

With this rowmovehandle, you only need to add it to headercolumncell instead of the original default movehandle. The specific method is to overwrite the createselectionhandles () method of dragroweditpolicy, the default Implementation of resizableeditpolicy for this method is to add a black box and eight control points, and we need to change it to the following:

ProtectedList createselectionhandles () {list l=NewArraylist ();//Black border aroundL. Add (NewRowmovehandle (graphicaleditpart) gethost ()));//Control points belowL. Add (NewRowresizehandle (graphicaleditpart) gethost (), positionconstants. South ));ReturnL ;}

The rowresizehandle class used in the Code is the custom implementation of control points, which will be discussed soon below. Now, you can see the effect of the entire row being selected.


Figure 3 select the entire row

Change the Row Height

The natural way to change the row height is to allow the user to freely drag the following edge after selecting the row. As mentioned above, resizehandle in GEF has the function of adjusting the image size. The disadvantage is that resizehandle is a small square in black (or white, not the primary choice, we want it to be a line, so that the mouse pointer will change the size as long as it is placed at the bottom of the selected row. This requires us to implement the rowresizehandle class we just mentioned. It is a subclass of resizehandle and the code is as follows:

 Public   Class Rowresizehandle Extends  Resizehandle {  Public Rowresizehandle (graphicaleditpart owner, Int  Direction ){  Super  (Owner, direction );  //  Change the size of the control point to a line. Setpreferredsize ( New Dimension (headercellpart) owner). getrowbound (). Width, 2 ));}  Public  Rowresizehandle (graphicaleditpart owner, locator Loc, cursor c ){  Super  (Owner, Loc, c );}  //  By default, the control point has a stroke, so we do not need to overwrite this method.      Public   Void  Paintfigure (Graphics g) {rectangle R =Getbounds (); G. setbackgroundcolor (getfillcolor (); G. fillrectangle (R. X, R. Y, R. Width, R. Height );}  //  Similar to rowmovehandle, but returns relativehandlelocator to display the line below the Graph      Public  Locator getlocator () {ifigure reffigure = New  Figure (); rectangle rect = (Headercellpart) getowner (). getrowbound (); translatetoabsolute (rect); reffigure. setbounds (rect );  Return   New Relativehandlelocator (reffigure, positionconstants. South );}  //  Whether or not it is the primary choice, black fill is used      Protected  Color getfillcolor (){  Return  Colorconstants. Black ;}} 

In this way, we pull the control point into the control line, because its Position overlaps with a part of the rowmovehandle, so we cannot feel its existence on the interface, however, you can use it to control the Row Height. See.


Figure 4 tips for changing the Row Height

Correct echo image

We know that when you drag a graph or change its size, GEF displays a ghost shape as the ECHO, that is, displaying the new position and size information of the graph. Because the target object is actually a cell when the operation is performed, the echo is also a cell by default (the width is the same as the column width ). Therefore, the getinitialfeedbackbounds () method must be overwritten in dragroweditpolicy. The rectangle returned by this method determines the initial state of the image when the Mouse starts to drag. See the following code:

ProtectedRectangle getinitialfeedbackbounds (){Return(Headercellpart) gethost (). getrowbound ();}

In this case, you can use the same echo when dragging a row.


Figure 5 echo when the row is changed

After the above modification, the operation on headercell is fully performed on the interface as an operation on table rows. The results of these operations will be converted to some commands, including createheadercellcommand (create a new row, you can also name it createrowcommand), moveheadercellcommand (move row), deleteheadercellcommand (Delete row) and changeheadercellheightcommand (Change Row Height). In these classes, you must perform the same operation on all columns (for example, changing the height of headercell and changing the height of other cells in the same row ), in this way, the appearance of the table can be maintained on the interface. The detailed code does not need to be pasted here.

P.s. has considered another way to implement tables, that is, the model only has two types of objects: Table and cell, and then write a tablelayout to take charge of the Cell Layout. It is also because the modification workload is relatively large and not used, because in that case, the rows and columns must be processed in a custom way, and the method described in this post only cares about the row processing. Of course, what we are talking about here is not a standard implementation, but the results are still good and can indeed be implemented. If you have similar requirements, you can serve as a reference.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.